必须进行支持的游戏方可使用此功能_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,一经查实,立即删除!

相关文章

FOR JENNIFER MORRISON

豪斯医生里面这女子真是感觉越来越好看了&#xff0c;唉~ 白天一直在写代码&#xff0c;感觉自己非常2B&#xff0c;选择了一个非常臃肿容易出错的方式来完成一个本来很容易的问题。 那就是用状态机嵌套&#xff0c;大的状态机来操作整个模块的动作是没有错误的&#xff0c;但是…

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;…

[html] 写个布局,当页面高度不够时,底部固定在下面,反之不固定

[html] 写个布局&#xff0c;当页面高度不够时&#xff0c;底部固定在下面&#xff0c;反之不固定 <div class"layout"> <header class"header"><!-- header 内容 …… --></header><div class"page"><slot /…

信号量与令牌桶_限流的4种方式令牌桶实战

限流的4种方式正文限流限流是对某一时间窗口内的请求数进行限制&#xff0c;保持系统的可用性和稳定性&#xff0c;防止因流量暴增而导致的系统运行缓慢或宕机。常用的限流算法有令牌桶和和漏桶&#xff0c;而Google开源项目Guava中的RateLimiter使用的就是令牌桶控制算法。在开…

采用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…

[html] 使用递归时应该注意哪些问题?

[html] 使用递归时应该注意哪些问题&#xff1f; 必须要有正确的结束条件避免占用太多栈而爆掉&#xff0c;可限制最大栈数报警或异步分批注意类似对象引用自身的无限循环情况个人简介 我是歌谣&#xff0c;欢迎和大家一起交流前后端知识。放弃很容易&#xff0c; 但坚持一定很…

手机恢复出厂设置命令_擦除数据/恢复出厂设置通过ADB

经过大量的挖掘后&#xff0c;我终于下载了Android的恢复部分的源代码。事实证明&#xff0c;你实际上可以发送命令到恢复。* The arguments which may be supplied in the recovery.command file:* --send_intentanystring - write the text out to recovery.intent* --update…

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;未知点在上述已知点自变量范围内…

element select 自动展开_js触发select自动展开

Q1&#xff1a;javascript模拟select,jselect的方法实现由于主流浏览器对select元素渲染不同&#xff0c;所以在每种浏览器下显示也不一样&#xff0c;最主要的是默认情况下UI太粗糙&#xff0c;即使通过css加以美化也不能达到很美观的效果。这对于我们这些专注于UX的前端开发人…

[html] 举例说明html的修饰元素有哪些?

[html] 举例说明html的修饰元素有哪些&#xff1f; 加粗&#xff1a;strong、b 倾斜&#xff1a;i、em 下划线&#xff1a;ins 删除线&#xff1a;del 自带样式&#xff1a;p、ul、ol、li、table、tr、td、thead、tbody等个人简介 我是歌谣&#xff0c;欢迎和大家一起交流前后…

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的安装路径&…

[转] 【领导必读】唐僧为什么可以领导孙悟空

小时候读西游记总有一个疑问——那个唐僧那么无能&#xff0c;为什么孙悟空非要带着他去取经呢&#xff1f;如果孙悟空自己去取经&#xff0c;不就麻烦少多了么&#xff1f;后来长大了&#xff0c;工作了&#xff0c;先被人领导&#xff0c;之后又领导别人&#xff0c;总算明白…

python plt.show_如何使用Python最大化plt.show()窗口

因爲我在零信譽我不會留下任何其他的標誌而不是新的答案 我在Windows(WIN7)上運行Python 2.7.5 & Matplotlib 1.3。1我能夠使用以下行以最大化TkAgg&#xff0c;QT4Agg和wxAgg圖窗口&#xff1a;from matplotlib import pyplot as plt### for TkAgg backendplt.figure(1)pl…

ufw防火墙规则不生效

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

[html] html的标签元素分为哪几大类?分别有什么作用?

[html] html的标签元素分为哪几大类&#xff1f;分别有什么作用&#xff1f; 行内&#xff0c;块&#xff0c;行内块&#xff1b;单&#xff0c;双&#xff1b;个人简介 我是歌谣&#xff0c;欢迎和大家一起交流前后端知识。放弃很容易&#xff0c; 但坚持一定很酷。欢迎大家…

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

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

uva minesweep 水题

格式控制那块&#xff0c;用cin输入&#xff0c;输出的时候有问题&#xff0c;但不知道为什么能过 不知道是不是我理解错了 #include <cstdio> #include <iostream> using namespace std;char a[102][102];int n,m;int add(int q,int p) {int mines0;if(a[q][p]*)r…