必须进行支持的游戏方可使用此功能_C#8.0 新增功能

(给DotNet加星标,提升.Net技能)

转自:张传宁cnblogs.com/SavionZhang/p/11201818.html

C#8.0提供了许多增强功能

1、Readonly 成员

可将 readonly 修饰符应用于结构的任何成员。它指示该成员不会修改状态。这比将 readonly 修饰符应用于 struct 声明更精细。请考虑以下可变结构:

public struct Point
{
public double X { get; set; }
public double Y { get; set; }
public double Distance => Math.Sqrt(X * X + Y * Y);
public override string ToString() => $"({X}, {Y}) is {Distance} from the origin";
}

像大多数结构一样, ToString() 方法不会修改状态。可以通过将 readonly 修饰符添加到 ToString() 的声明来对此进行指示:

public readonly override string ToString() => $"({X}, {Y}) is {Distance} from the origin";

上述更改会生成编译器警告,因为 ToString 访问 Distance 属性,该属性未标记为 readonly:

warning CS8656: Call to non-readonly
member 'Point.Distance.get'
from a 'readonly' member
results in an implicit copy of 'this'

需要创建防御性副本时,编译器会发出警告。Distance 属性不会更改状态,因此可以通过将 readonly 修饰符添加到声明来修复此警告:

public readonly double 
Distance => Math.Sqrt(X * X + Y * Y);

请注意,readonly 修饰符对于只读属性是必需的。编译器不会假设 get 访问器不修改状态;必须明确声明 readonly。编译器会强制实施以下规则:readonly 成员不修改状态。除非删除 readonly 修饰符,否则不会编译以下方法:

public readonly void Translate(int xOffset, int yOffset){
X += xOffset;
Y += yOffset;
}

8f30b2cc6a6f310e676bb8d9fb409b00.png

通过此功能,可以指定设计意图,使编译器可以强制执行该意图,并基于该意图进行优化。

2、默认接口成员【*重要*】

现在可以将成员添加到接口,并为这些成员提供实现。借助此语言功能,API 作者可以将方法添加到以后版本的接口中,而不会破坏与该接口当前实现的源或二进制文件兼容性。现有的实现继承默认实现 。此功能使 C# 与面向 Android 或 Swift 的 API 进行互操作,此类 API 支持类似功能。默认接口成员还支持类似于“特征”语言功能的方案。

默认接口成员会影响很多方案和语言元素。请参考 C#8.0 中使用默认接口成员更新接口。

3、在更多位置中使用更多模式

模式匹配 提供了在相关但不同类型的数据中提供形状相关功能的工具。C# 7.0 通过使用 is表达式和 switch 语句引入了类型模式和常量模式的语法。这些功能代表了支持数据和功能分离的编程范例的初步尝试。随着行业转向更多微服务和其他基于云的体系结构,还需要其他语言工具。

C# 8.0 扩展了此词汇表,这样就可以在代码中的更多位置使用更多模式表达式。当数据和功能分离时,请考虑使用这些功能。当算法依赖于对象运行时类型以外的事实时,请考虑使用模式匹配。这些技术提供了另一种表达设计的方式。

除了可以在新位置使用新模式之外,C# 8.0 还添加了“递归模式” 。任何模式表达式的结果都是一个表达式。递归模式只是应用于另一个模式表达式输出的模式表达式。

Switch 表达式

通常情况下,switch 语句在其每个 case 块中生成一个值。借助 Switch 表达式 ,可以使用更简洁的表达式语法。只有些许重复的 case 和 break 关键字和大括号。以下面列出彩虹颜色的枚举为例:

public enum Rainbow
{
Red,
Orange,
Yellow,
Green,
Blue,
Indigo,
Violet
}

如果应用定义了通过 R、G 和 B 组件构造而成的 RGBColor 类型,可使用以下包含 switch 表达式的方法,将 Rainbow 转换为 RGB 值:

public static RGBColor FromRainbow(Rainbow colorBand) =>
colorBand switch
{
Rainbow.Red => new RGBColor(0xFF, 0x00, 0x00),
Rainbow.Orange => new RGBColor(0xFF, 0x7F, 0x00),
Rainbow.Yellow => new RGBColor(0xFF, 0xFF, 0x00),
Rainbow.Green => new RGBColor(0x00, 0xFF, 0x00),
Rainbow.Blue => new RGBColor(0x00, 0x00, 0xFF),
Rainbow.Indigo => new RGBColor(0x4B, 0x00, 0x82),
Rainbow.Violet => new RGBColor(0x94, 0x00, 0xD3),
_ => throw new ArgumentException(message: "invalid enum value", paramName: nameof(colorBand)),
};

这里有几个语法改进:

  • 变量位于 switch 关键字之前。不同的顺序使得在视觉上可以很轻松地区分 switch 表达式和 switch 语句。

  • 将 case 和 : 元素替换为 =>。它更简洁,更直观。

  • 将 default 事例替换为 _ 弃元。

  • 正文是表达式,不是语句。

将其与使用经典 switch 语句的等效代码进行对比:

public{switch (colorBand)

属性模式

借助属性模式 ,可以匹配所检查的对象的属性。请看一个电子商务网站的示例,该网站必须根据买家地址计算销售税。这种计算不是 Address 类的核心职责。

它会随时间变化,可能比地址格式的更改更频繁。销售税的金额取决于地址的 State 属性。下面的方法使用属性模式从地址和价格计算销售税:

public static decimal ComputeSalesTax(Address location, decimal salePrice) =>
location switch
{
{ State: "WA" } => salePrice * 0.06M,
{ State: "MN" } => salePrice * 0.75M,
{ State: "MI" } => salePrice * 0.05M,
// other cases removed for brevity...
_ => 0M
};

模式匹配为表达此算法创建了简洁的语法。

元组模式

一些算法依赖于多个输入。使用元组模式,可根据表示为元组的多个值进行切换 。以下代码显示了游戏“rock, paper, scissors(石头剪刀布)”的切换表达式::

public static string RockPaperScissors(string first, string second)
=> (first, second) switch
{
("rock", "paper") => "rock is covered by paper. Paper wins.",
("rock", "scissors") => "rock breaks scissors. Rock wins.",
("paper", "rock") => "paper covers rock. Paper wins.",
("paper", "scissors") => "paper is cut by scissors. Scissors wins.",
("scissors", "rock") => "scissors is broken by rock. Rock wins.",
("scissors", "paper") => "scissors cuts paper. Scissors wins.",
(_, _) => "tie"
};

消息指示获胜者。弃元表示平局(石头剪刀布游戏)的三种组合或其他文本输入。

位置模式

某些类型包含 Deconstruct 方法,该方法将其属性解构为离散变量。如果可以访问 Deconstruct 方法,就可以使用位置模式 检查对象的属性并将这些属性用于模式。考虑以下 Point 类,其中包含用于为 X 和 Y 创建离散变量的 Deconstruct 方法:

public class Point
{
public int X { get; }
public int Y { get; }
public Point(int x, int y) => (X, Y) = (x, y);
public void Deconstruct(out int x, out int y) => (x, y) = (X, Y);
}

此外,请考虑以下表示象限的各种位置的枚举:

public enum Quadrant
{
Unknown,
Origin,
One,
Two,
Three,
Four,
OnBorder
}

下面的方法使用位置模式 来提取 x 和 y 的值。然后,它使用 when 子句来确定该点的 Quadrant:

static Quadrant GetQuadrant(Point point) => point switch
{
(0, 0) => Quadrant.Origin,
var (x, y) when x > 0 && y > 0 => Quadrant.One,
var (x, y) when x < 0 && y > 0 => Quadrant.Two,
var (x, y) when x < 0 && y < 0 => Quadrant.Three,
var (x, y) when x > 0 && y < 0 => Quadrant.Four,
var (_, _) => Quadrant.OnBorder,
_ => Quadrant.Unknown
};

当 x 或 y 为 0(但不是两者同时为 0)时,前一个开关中的弃元模式匹配。Switch 表达式必须要么生成值,要么引发异常。如果这些情况都不匹配,则 switch 表达式将引发异常。如果没有在 switch 表达式中涵盖所有可能的情况,编译器将生成一个警告。

可在此模式匹配高级教程中探索模式匹配方法。

4、using 声明

using 声明 是前面带 using 关键字的变量声明。它指示编译器声明的变量应在封闭范围的末尾进行处理。以下面编写文本文件的代码为例:

static void WriteLinesToFile(IEnumerable<string> lines){
using var file = new System.IO.StreamWriter("WriteLines2.txt");
foreach (string line in lines)
{
// 如果该行不包含单词“second”,则将该行写入文件。
if (!line.Contains("Second"))
{
file.WriteLine(line);
}
}
// 文件已在此处释放
}

在前面的示例中,当到达方法的右括号时,将对该文件进行处理。这是声明 file 的范围的末尾。前面的代码相当于下面使用经典 using 语句语句的代码:

static void WriteLinesToFile(IEnumerable<string> lines){
using (var file = new System.IO.StreamWriter("WriteLines2.txt"))
{
foreach (string line in lines)
{
// 如果该行不包含单词“second”,则将该行写入文件。
if (!line.Contains("Second"))
{
file.WriteLine(line);
}
}
} // 文件已在此处被释放
}

在前面的示例中,当到达与 using 语句关联的右括号时,将对该文件进行处理。

在这两种情况下,编译器将生成对 Dispose() 的调用。如果 using 语句中的表达式不可处置,编译器将生成一个错误。

5、静态本地函数

现在可以向本地函数添加 static 修饰符,以确保本地函数不会从封闭范围捕获(引用)任何变量。

这样做会生成 CS8421,“静态本地函数不能包含对 的引用”。

考虑下列代码。本地函数 LocalFunction 访问在封闭范围(方法 M)中声明的变量 y。因此,不能用 static 修饰符来声明 LocalFunction:

int M(){
int y;
LocalFunction();
return y;
void LocalFunction() => y = 0;
}

下面的代码包含一个静态本地函数。它可以是静态的,因为它不访问封闭范围中的任何变量:

int M(){
int y = 5;
int x = 7;
return Add(x, y);
static int Add(int left, int right) => left + right;
}

6、可处置的 ref 结构

用 ref 修饰符声明的 struct 可能无法实现任何接口,因此无法实现 IDisposable。

因此,要能够处理 ref struct,它必须有一个可访问的 void Dispose() 方法。

这同样适用于 readonly ref struct 声明。

7、可为空引用类型

在可为空注释上下文中,引用类型的任何变量都被视为不可为空引用类型 。 

若要指示一个变量可能为 null,必须在类型名称后面附加 ?,以将该变量声明为可为空引用类型 。

对于不可为空引用类型,编译器使用流分析来确保在声明时将本地变量初始化为非 Null 值。

字段必须在构造过程中初始化。如果没有通过调用任何可用的构造函数或通过初始化表达式来设置变量,编译器将生成警告。此外,不能向不可为空引用类型分配一个可以为 Null 的值。

不对可为空引用类型进行检查以确保它们没有被赋予 Null 值或初始化为 Null。不过,编译器使用流分析来确保可为空引用类型的任何变量在被访问或分配给不可为空引用类型之前,都会对其 Null 性进行检查。

可以在可为空引用类型的概述中了解该功能的更多信息。可以在此可为空引用类型教程中的新应用程序中自行尝试。在迁移应用程序以使用可为空引用类型教程中了解迁移现有代码库以使用可为空引用类型的步骤。

8、异步流【*重要*】

从 C# 8.0 开始,可以创建并以异步方式使用流。返回异步流的方法有三个属性:

  • 它是用 async 修饰符声明的。

  • 它将返回 IAsyncEnumerable。

  • 该方法包含用于在异步流中返回连续元素的 yield return 语句。

使用异步流需要在枚举流元素时在 foreach 关键字前面添加 await 关键字。 

添加 await 关键字需要枚举异步流的方法,以使用 async 修饰符进行声明并返回 async 方法允许的类型。通常这意味着返回 Task 或 Task。 

也可以为 ValueTask 或 ValueTask。方法既可以使用异步流,也可以生成异步流,这意味着它将返回 IAsyncEnumerable。 

下面的代码生成一个从 0 到 19 的序列,在生成每个数字之间等待 100 毫秒:

public static async System.Collections.Generic.IAsyncEnumerable<int> GenerateSequence(){
for (int i = 0; i < 20; i++)
{
await Task.Delay(100);
yield return i;
}
}

可以使用 await foreach 语句来枚举序列:

await foreach (var number in GenerateSequence()){
Console.WriteLine(number);
}

可以在创建和使用异步流的教程中自行尝试异步流。

9、索引和范围

范围和索引为在数组中指定子范围(Span 或 ReadOnlySpan)提供了简洁语法。

此语言支持依赖于两个新类型和两个新运算符。

  • System.Index 表示一个序列索引。

  • ^ 运算符,指定一个索引与序列末尾相关。

  • System.Range 表示序列的子范围。

  • 范围运算符 (..),用于指定范围的开始和末尾,就像操作数一样。

让我们从索引规则开始。请考虑数组 sequence。 

0 索引与 sequence[0] 相同。 

^0 索引与 sequence[sequence.Length] 相同。 

请注意,sequence[^0] 不会引发异常,就像 sequence[sequence.Length] 一样。 

对于任何数字 n,索引 ^n 与 sequence.Length - n 相同。

范围指定范围的开始和末尾 。 

包括此范围的开始,但不包括此范围的末尾,这表示此范围包含开始但不包含末尾。

范围 [0..^0] 表示整个范围,就像 [0..sequence.Length] 表示整个范围。

请看以下几个示例。 

请考虑以下数组,用其顺数索引和倒数索引进行注释:

var words = new string[]
{
// index from start index from end
"The", // 0 ^9
"quick", // 1 ^8
"brown", // 2 ^7
"fox", // 3 ^6
"jumped", // 4 ^5
"over", // 5 ^4
"the", // 6 ^3
"lazy", // 7 ^2
"dog" // 8 ^1
}; // 9 (or words.Length) ^0

可以使用 ^1 索引检索最后一个词:

Console.WriteLine($"The last word is {words[^1]}");
// writes "dog"

以下代码创建了一个包含单词“quick”、“brown”和“fox”的子范围。

它包括 words[1] 到 words[3]。元素 words[4] 不在此范围内。

var quickBrownFox = words[1..4];

以下代码使用“lazy”和“dog”创建一个子范围。

它包括 words[^2] 和 words[^1]。不包括结束索引 words[^0]:

var lazyDog = words[^2..^0];

下面的示例为开始和/或结束创建了开放范围:

var allWords = words[..];
// contains "The" through "dog".
var firstPhrase = words[..4];
// contains "The" through "fox"
var lastPhrase = words[6..];
// contains "the", "lazy" and "dog"

此外可以将范围声明为变量:

Range phrase = 1..4;

然后可以在 [ 和 ] 字符中使用该范围:

var text = words[phrase];

可在有关索引和范围的教程中详细了解索引和范围。

推荐阅读

(点击标题可跳转阅读)

C#各版本新增加功能(系列文章)

C# 8.0两个有趣的新特性以及gRPC

聊一聊C#8.0中的 await foreach

看完本文有收获?请转发分享给更多人

关注「DotNet」加星标,提升.Net技能 

79b110a4a46f878250d35617eab2e6fe.png

好文章,我在看❤️

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/409978.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Zabbix 3.0 配置企业微信报警(配置zabbix-web)

一、添加报警媒体类型 Name&#xff1a;自定义 Type&#xff1a;选择script Scripts name&#xff1a;填写脚本名称 Script parameters&#xff1a;脚本参数--corpidXXX--corpsecretXXX--user{ALERT.SENDTO}--msg{ALERT.MESSAGE}--agentidXXX最后点Add即可添加完成&#xff1b;…

采用python解决实际问题_Python编程语言解决几种常见的实际问题

Python编程语言解决几种常见的实际问题 (2012-10-25 17:24:12) 标签&#xff1a; it python python培训 北京 杂谈 Python编程语言解决一些实际问题 from os.path import walk, join, normpath from os import chdir, remove def scan(arg, dirname, names) for file in names:…

EevExpress中XtraGrid常用方法

1.girdView在第一列显示行号 调整第一列的宽度 gridView1.IndicatorWidth 40; View Code 1 private void gridView1_CustomDrawRowIndicator(object sender, DevExpress.XtraGrid.Views.Grid.RowIndicatorCustomDrawEventArgs e)2 { 3 if (e.Info.IsRowIndi…

【转载】博客园编辑数学公式的方法

原文在这里&#xff1a;博客园编辑数学公式的方法 需要在选项中勾上 启用数学公式支持 在公式开始和结尾输入美元符号 &#xff1a; 如 美元符号x^2美元符号 则显示x的平方 x^2 需要在http://latex.codecogs.com/eqneditor/editor.php里面编辑好后复制源码过来。 如 转载于:htt…

php代码里怎么写html代码_菜鸟青铜变白银!Python 项目代码写完了,然后怎么打包和发布?...

你把你的代码写完了&#xff0c;是不是要给别人使用下&#xff0c;怎么打包你的项目代码呢&#xff1f;喂&#xff0c;开源么&#xff1f;接下来小帅b就跟你说说&#xff0c;如何打包你的代码。就拿我们上次演示的 todo为例&#xff0c;写完代码之后&#xff0c;代码的目录是这…

三次样条插值 cubic spline interpolation

什么是三次样条插值 插值&#xff08;interpolation&#xff09;是在已知部分数据节点&#xff08;knots&#xff09;的情况下&#xff0c;求解经过这些已知点的曲线&#xff0c; 然后根据得到的曲线进行未知位置点函数值预测的方法&#xff08;未知点在上述已知点自变量范围内…

vscode python环境_在vscode中配置python环境

原博文 2019-09-27 22:55 − 1.安装vscode和python3.7&#xff08;安装路径在&#xff1a;E:\Python\Python37&#xff09;&#xff1b; 2.打开vscode&#xff0c;在左下角点击设置图标选择setting&#xff0c;搜索python path&#xff0c;在该路径下选择python的安装路径&…

ufw防火墙规则不生效

正式站系统是Ubuntu 16.04.6 一、今天一个项目有百度爬出&#xff0c;在nginx中封掉还在一直爬取&#xff0c;都403还不停爬取 二、在uwf封掉爬出ip&#xff0c;想封掉80端口没有用&#xff0c;然后封掉整个网段还是没有用&#xff0c;尴尬 三、放出终极大招 UFW(iptables)规则…

network怎么断点调试_Windows 网络编程:调试 API

一次性进群&#xff0c;长期免费索取教程&#xff0c;没有付费教程。教程列表见微信公众号底部菜单进微信群回复公众号&#xff1a;微信群&#xff1b;QQ群&#xff1a;460500587微信公众号&#xff1a;计算机与网络安全ID&#xff1a;Computer-network在Windows中有这么一些AP…

非会员只能试看20分钟_做欧包都要把铁锅烤半小时?太费电了,用我这办法只需预热几分钟...

最近迷上了做欧包&#xff0c;做欧包要用蒸烤箱&#xff0c;做好的欧包才会外脆内软&#xff0c;如果没有蒸烤箱的话人们又研究出了用铸铁锅来做&#xff0c;先把铸铁锅放在烤箱里烘烤半小时左右&#xff0c;然后把面包坯子放入铸铁锅盖好盖子迅速放回烤箱&#xff0c; 因为锅的…

顺序表归并

对两个顺序表进行合并。 思想&#xff1a;定义两个变量&#xff08;i&#xff0c;j&#xff09;分别指向顺序表 A和B当前处理的元素&#xff0c;若i元素不大于j元素&#xff08;<&#xff09;&#xff0c;则把i元素复制到新表中&#xff0c;否者将j元素复制到新表中。 View …

collection集合 多少钱_Java集合框架大汇总,建议收藏

Java集合Java集合框架&#xff1a;是一种工具类&#xff0c;就像是一个容器可以存储任意数量的具有共同属性的对象。Java集合中成员很丰富&#xff0c;常用的集合有ArrayList&#xff0c;HashMap&#xff0c;HashSet等。线程安全的有Vector&#xff0c;HashTable。线程不安全的…

python识别简单训练模型_使用已经得到的keras模型识别自己手写的数字方式

环境&#xff1a;Pythonkeras&#xff0c;后端为Tensorflow 训练集&#xff1a;MNIST 对于如何训练一个识别手写数字的神经网络&#xff0c;网上资源十分丰富&#xff0c;并且能达到相当高的精度。但是很少有人涉及到如何将图片输入到网络中并让已经训练好的模型惊醒识别&#…

程旭元系统漫画第三期:加班 !

对于苦逼的程旭元来说 加班已经变成了生活中不可缺少的部分 他的原则是不能像胖子那样贪吃 不能像销售员那样狡诈 一定要尽忠职守 精忠报国 &#xff01;老板说什么他就做什么&#xff01; 对于一个从来只说加班不加工资的boss来说 唯命是从就是存活在公司的最好方式~ 但是有…

python 的库如何开发_一篇文章入门Python生态系统

译者按&#xff1a;原文写于2011年末&#xff0c;虽然文中关于Python 3的一些说法可以说已经不成立了&#xff0c;但是作为一篇面向从其他语言转型到Python的程序员来说&#xff0c;本文对Python的生态系统还是做了较为全面的介绍。文中提到了一些第三方库&#xff0c;但是Pyth…

Nginx编译安装和平滑升级

一、Nginx的编译安装 1、安装依赖包gcc&#xff0c;gcc-c&#xff0c;pcre&#xff0c;openssl-devel 命令&#xff1a;yum -y install gcc gcc-c pcre-devel openssl-devel 2、下载Nginx源码包 Nginx下载地址&#xff1a;http://nginx.org/download/nginx-1.12.2.tar.gz …

android ListView详解

在android开发中ListView是比较常用的组件&#xff0c;它以列表的形式展示具体内容&#xff0c;并且能够根据数据的长度自适应显示。抽空把对ListView的使用做了整理&#xff0c;并写了个小例子&#xff0c;如下图。 列表的显示需要三个元素&#xff1a;1&#xff0e;ListVeiw …

Nginx网站用户认证

一、Nginx网站用户认证 用户认证&#xff1a;用户访问网页时需要输入一个用户名和密码才能打开网页。 nginx的默认网页时安装目录下的html/index.html&#xff0c;配置文件在安装目录下的conf目录中的nginx.conf 无用户认证网页 修改配置文件/usr/local/nginx/conf/nginx.conf(…

Nginx基于域名的虚拟主机

一、基于域名的虚拟主机 修改配置文件/usr/local/nginx/conf/nginx.conf 创建新的虚拟主机的根目录和默认网页index.html 重新加载nginx的配置文件 查看两个虚拟主机 因为这两个域名是随便写的&#xff0c;所以需要修改windows系统的hosts文件&#xff0c;让电脑能够解析www.a.…