C# 8.0 的新特性概览和讲解
本文转自 https://blog.csdn.net/hez2010/article/details/84036742
C# 8.0 的新特性概览和讲解
前言
该文章的最新版本已迁移至个人博客【比特飞】,单击链接 https://www.byteflying.com/archives/1037 访问。
2018年11月12日微软在 MSDN 博客的 Building C# 8.01 一文发表了新的 C# 8.0 即将发布的特性,现在让我们来看一下。
新的改变
- 可空引用类型
- 异步流
- 范围和下标类型
- 接口成员的默认实现
- 模式匹配表达式和递归模式语句
- 目标类型推导
可空引用类型(Nullable reference types)
从此,引用类型将会区分是否可分,可以从根源上解决 NullReferenceException。但是由于这个特性会打破兼容性,因此没有当作 error 来对待,而是使用 warning 折衷,而且开发人员需要手动 opt-in 才可以使用该特性(可以在项目层级或者文件层级进行设定)。
例如:
string s = null; // 产生警告: 对不可空引用类型赋值 null
string? s = null; // Ok
void M(string? s)
{
Console.WriteLine(s.Length); // 产生警告:可能为 null
if (s != null)
{
Console.WriteLine(s.Length); // Ok
}
}
至此,妈妈再也不用担心我的程序到处报 NullReferenceException 啦!
异步流(Async streams)
考虑到大部分 Api 以及函数实现都有了对应的 async
版本,而 IEnumerable<T>
和 IEnumerator<T>
还不能方便的使用 async
/await
就显得很麻烦了。
但是,现在引入了异步流,这些问题得到了解决。
我们通过新的 IAsyncEnumerable<T>
和 IAsyncEnumerator<T>
来实现这一点。同时,由于之前 foreach
是基于IEnumerable<T>
和 IEnumerator<T>
实现的,因此引入了新的语法await foreach
来扩展 foreach
的适用性。
例如:
async Task<int> GetBigResultAsync()
{
var result = await GetResultAsync();
if (result > 20) return result;
else return -1;
}
async IAsyncEnumerable<int> GetBigResultsAsync()
{
await foreach (var result in GetResultsAsync())
{
if (result > 20) yield return result;
}
}
范围和下标类型(Ranges and indices)
C# 8.0 引入了 Index 类型,可用作数组下标,并且使用 ^ 操作符表示倒数。
不过要注意的是,倒数是从 1 开始的。
Index i1 = 3; // 下标为 3
Index i2 = ^4; // 倒数第 4 个元素
int[] a = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
Console.WriteLine($"{a[i1]}, {a[i2]}"); // "3, 6"123123
除此之外,还引入了 “…” 操作符用来表示范围(注意是左闭右开区间)。
var slice = a[i1..i2]; // { 3, 4, 5 }
关于这个下标从 0 开始,倒数从 1 开始,范围左闭右开,笔者刚开始觉得很奇怪,但是发现 Python 等语言早已经做了这样的实践,并且效果不错。因此这次微软也采用了这种方式设计了 C# 8.0 的这个语法。
接口的默认实现方法(Default implementations of interface members)
从此接口中可以包含实现了:
interface ILogger
{
void Log(LogLevel level, string message);
void Log(Exception ex) => Log(LogLevel.Error, ex.ToString()); // 这是一个默认实现重载
}
class ConsoleLogger : ILogger
{
public void Log(LogLevel level, string message) { ... }
// Log(Exception) 会得到执行的默认实现
}
在上面的例子中,Log(Exception)
将会得到执行的默认实现。
模式匹配表达式和递归模式语句(Switch expressions and recursive patterns)
现在可以这么写了(patterns 里可以包含 patterns)
IEnumerable<string> GetEnrollees()
{
foreach (var p in People)
{
if (p is Student { Graduated: false, Name: string name }) yield return name;
}
}
Student { Graduated: false, Name: string name }
检查 p 是否为 Graduated = false
且 Name
为 string
的 Student
,并且迭代返回 name
。
可以这样写之后是不是很爽?
更有:
var area = figure switch
{
Line _ => 0,
Rectangle r => r.Width * r.Height,
Circle c => c.Radius * 2.0 * Math.PI,
_ => throw new UnknownFigureException(figure)
};
典型的模式匹配语句,只不过没有用“match”关键字,而是沿用了
了“switch”关键字。
但是不得不说,一个字,爽!
目标类型推导(Target-typed new-expressions)
以前我们写下面这种变量/成员声明的时候,大概最简单的写法就是:
var points = new [] { new Point(1, 4), new Point(2, 6) };
private List<int> _myList = new List<int>();1212
现在我们可以这么写啦:
Point[] ps = { new (1, 4), new (3,-2), new (9, 5) };
private List<int> _myList = new ();1212
是不是更加的舒服了?
注意事项
该文章的最新版本已迁移至个人博客【比特飞】,单击链接 https://www.byteflying.com/archives/1037 访问。
- 以上的新特性需要 .NET Standard 2.1/.NET Core 3.0/.NET Framework 4.8 及以上来支持。
- 但是,由于接口的默认实现方法这个特性需要 CLR 的支持,而 .NET Framework 4.8 还没有来得及做出修改,因此此特性在 .NET Framework 4.8 中不可用,需要等待进一步的更新。
- C# 8.0 截至发文可以说已经定型了,正式发布还需要等一阵子。
一些想法
- 本次 C# 8.0 的更新,Record2估计是要被鸽了,有些小遗憾。
- C# 一直都在不断地完善和补充自己的语法体系,这和官方给出的 C# 发展目标相同,即:不断容纳各种优秀和现代的语法特性,追求多样化。相信这门优秀的语言未来会带给我们更多的惊喜。希望大家不要抱着老旧的看法对待这门语言,都 8012 年了我们也应该用全新的姿态去审视这门语言,去尝试一下新的语法对编码效率带来的大幅度提升。
- C# 的 IDE 除了 Visusl Studio 之外,还有 Visual Studio for Mac 以及跨平台的 Visual Studio Code、JetBrain 出品的 Rider 跨平台 C# IDE,极大程度的方便了开发者。
- 从近几年的发展来看,微软面对开源、生态建设、开发者、社区、跨平台等的重视程度不断上升,相信 .NET Core 的前景一定会更好。
参考文献
- https://blogs.msdn.microsoft.com/dotnet/2018/11/12/building-c-8-0 ︎
- https://github.com/dotnet/csharplang/issues/39 ︎
C# 8.0 的新特性概览和讲解的更多相关文章
- 你不知道的JavaScript--Item24 ES6新特性概览
ES6新特性概览 本文基于lukehoban/es6features ,同时参考了大量博客资料,具体见文末引用. ES6(ECMAScript 6)是即将到来的新版本JavaScript语言的标准,代 ...
- php5.3到php7.0.x新特性介绍
<?php /*php5.3*/ echo '<hr>'; const MYTT = 'aaa'; #print_r(get_defined_constants()); /* 5.4 ...
- paip.php 5.0 5.3 5.4 5.5 -6.0的新特性总结与比较
paip.php 5.0 5.3 5.4 5.5 -6.0的新特性总结与比较 PHP5的新特性 2 · 对象的参照过渡是默认的(default) 3 · 引入访问属性的限制 3 · 引入访问方法的限 ...
- NodeJS 框架 Express 从 3.0升级至4.0的新特性
NodeJS 框架 Express 从 3.0升级至4.0的新特性 [原文地址:√https://scotch.io/bar-talk/expressjs-4-0-new-features-and-u ...
- 相比于python2.6,python3.0的新特性。
这篇文章主要介绍了相比于python2.6,python3.0的新特性.更详细的介绍请参见python3.0的文档. Common Stumbling Blocks 本段简单的列出容易使人出错的变动. ...
- MySQL 8.0 InnoDB新特性
MySQL 8.0 InnoDB新特性 1.数据字典全部采用InnoDB引擎存储,支持DDL原子性.crash safe,metadata管理更完善 2.快速在线加新列(腾讯互娱DBA团队贡献) 3. ...
- Atitit jquery 1.4--v1.11 v1.12 v2.0 3.0 的新特性
Atitit jquery 1.4--v1.11 v1.12 v2.0 3.0 的新特性 1.1. Jquery1.12 jQuery 2.2 和 1.12 新版本发布 - OPEN资讯.h ...
- [PHP] 从PHP 5.6.x 移植到 PHP 7.0.x新特性
从PHP 5.6.x 移植到 PHP 7.0.x 新特性: 1.标量类型声明 字符串(string), 整数 (int), 浮点数 (float), 布尔值 (bool),callable,array ...
- servlet3.0 的新特性之二注解代替了web.xml配置文件
servlet3.0 的新特性: 注解代替了 web.xml 文件 支持了对异步的处理 对上传文件的支持 1.注解代替了配置文件 1.删除了web.xml 文件 2. 在Servlet类上添加@Web ...
随机推荐
- JavaScript定时器及回调用法
JavaScript定时器及回调用法 循环定时任务 // 假设现在有这样一个需求:我需要请求一个接口,根据返回结果判断需不需要重复请求,直到达到某一条件为止,停止请求执行某操作 <script ...
- 从连接器组件看Tomcat的线程模型——NIO模式
Tomcat8之后,针对Http协议默认使用org.apache.coyote.http11.Http11NioProtocol,也就是NIO模式.通过之前的博客分析,我们知道Connector组件在 ...
- 【Python学习笔记一】基础环境安装:idea+python
IDEA 安装 1.下载IDEA 官网下载地址: https://www.jetbrains.com/idea/ 2.安装的时候配置基本选择默认配置就行 参考链接:https://blog.csd ...
- .net core https 双向验证
文章来自:https://www.cnblogs.com/axzxs2001/p/10070562.html 关于https双向认证的知识可先行google,这时矸接代码. 为了双向认证,我们首先得准 ...
- Problem H: 质心算法
Description 在很多应用中,需要对某个目标进行定位.比如对于一个未知坐标的点A,假定已知A点与N个点相邻,且已知N个相邻点的坐标,则可取N个点的质心作为A点坐标的一个估计值. 所谓质心,就是 ...
- Winform开发中的困境及解决方案
在我们开发各种应用的时候,都会碰到很多不同的问题,这些问题涉及架构.模块组合.界面处理.共同部分抽象等方面,我们这里以Winform开发为例,从系统模块化.界面组件选择.业务模块场景划分.界面基类和辅 ...
- 没想到 Hash 冲突还能这么玩,你的服务中招了吗?
背景 其实这个问题我之前也看到过,刚好在前几天,洪教授在某个群里分享的一个<一些有意思的攻击手段.pdf>,我觉得这个话题还是有不少人不清楚的,今天我就准备来“实战”一把,还请各位看官轻拍 ...
- Java MD5获取
MD5算法具有以下特点: 1.压缩性:任意长度的数据,算出的MD5值长度都是固定的. 2.容易计算:从原数据计算出MD5值很容易. 3.抗修改性:对原数据进行任何改动,哪怕只修改1个字节,所得到的MD ...
- String字符串缓冲区、StringBuffer
String字符串缓冲区 1.StringBuffer类 StringBuffer又称为可变字符序列,字符串缓冲区支持可变的字符串, StringBuffer是个字符串的缓冲区,即就是它是一个容器,容 ...
- pandas 几个重要知识点
将 NaN 替换成某一数值 使用 fillna dataframe.fillna(value = 'xxx',inplace=True) 删除某一个值 使用 drop dataframe.drop(1 ...