本文转自 https://blog.csdn.net/hez2010/article/details/84036742

前言

该文章的最新版本已迁移至个人博客【比特飞】,单击链接 https://www.byteflying.com/archives/1037 访问。

2018年11月12日微软在 MSDN 博客的 Building C# 8.01 一文发表了新的 C# 8.0 即将发布的特性,现在让我们来看一下。

新的改变

  1. 可空引用类型
  2. 异步流
  3. 范围和下标类型
  4. 接口成员的默认实现
  5. 模式匹配表达式和递归模式语句
  6. 目标类型推导

可空引用类型(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 = falseNamestringStudent,并且迭代返回 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 访问。

  1. 以上的新特性需要 .NET Standard 2.1/.NET Core 3.0/.NET Framework 4.8 及以上来支持。
  2. 但是,由于接口的默认实现方法这个特性需要 CLR 的支持,而 .NET Framework 4.8 还没有来得及做出修改,因此此特性在 .NET Framework 4.8 中不可用,需要等待进一步的更新。
  3. C# 8.0 截至发文可以说已经定型了,正式发布还需要等一阵子。

一些想法

  1. 本次 C# 8.0 的更新,Record2估计是要被鸽了,有些小遗憾。
  2. C# 一直都在不断地完善和补充自己的语法体系,这和官方给出的 C# 发展目标相同,即:不断容纳各种优秀和现代的语法特性,追求多样化。相信这门优秀的语言未来会带给我们更多的惊喜。希望大家不要抱着老旧的看法对待这门语言,都 8012 年了我们也应该用全新的姿态去审视这门语言,去尝试一下新的语法对编码效率带来的大幅度提升。
  3. C# 的 IDE 除了 Visusl Studio 之外,还有 Visual Studio for Mac 以及跨平台的 Visual Studio Code、JetBrain 出品的 Rider 跨平台 C# IDE,极大程度的方便了开发者。
  4. 从近几年的发展来看,微软面对开源、生态建设、开发者、社区、跨平台等的重视程度不断上升,相信 .NET Core 的前景一定会更好。

参考文献


  1. https://blogs.msdn.microsoft.com/dotnet/2018/11/12/building-c-8-0
  2. https://github.com/dotnet/csharplang/issues/39

最新文章

  1. JS获取屏幕高度(转)
  2. 用java实现zip压缩
  3. 在Ubuntu Trusty 14.04 (LTS) (64-bit)安装Docker
  4. SpringMVC 接收复杂对象
  5. c++基础(三):多态
  6. iOS 进阶 第十四天(0416)
  7. oracle to_date函数(转载)
  8. vs 点击就设置项目为默认启动项
  9. (转)java 23种设计模式
  10. Spark Scheduler模块源码分析之DAGScheduler
  11. 【keras】用tensorboard监视CNN每一层的输出
  12. 在vue项目中mock数据
  13. checkpoint NGFW 实验(一)
  14. A1051. Pop Sequence
  15. LeetCode] binaryTreePaths
  16. MySQL升级后1728错误解决方案
  17. mongodb int型id 自增
  18. jmeter测试java代码
  19. Kubernetes 1.5 配置dashboard
  20. pyqt5事件与鼠标事件

热门文章

  1. Ethical Hacking - NETWORK PENETRATION TESTING(8)
  2. Python Ethical Hacking - Persistence(2)
  3. Bash 脚本编程
  4. 题解 CF510E 【Fox And Dinner】
  5. 题解 洛谷 P4492 【[HAOI2018]苹果树】
  6. 转载 npm 安装vue出现的问题
  7. kotlin中使用Handler
  8. 前端学习(十三):CSS盒子模型
  9. .NET Core 微服务—API网关(Ocelot) 教程 [二]
  10. Text多行文本框基本用法