C# 8.0 新特性

  [译注:原文主标题如此,但内容大部分为新特性介绍,所以意译标题为 "C# 8.0 新特性"]
  
  C# 的下一个主要版本是 8.0。我们已经为它工作了很长一段时间,即使我们构建并发布了次要版本 C# 7.1, 7.2 和 7.3,我仍然对 8.0 将带来的新特性感到非常兴奋。
  
  目前的计划是 C# 8.0 将与 .NET Core 3.0 同时发布。然而,随着我们正在开发的 Visual Studio 2019 的预览版,这些特性将开始活跃起来。当这些出来的时候,您就可以开始尝试它们,我们将提供有关各个特性的更多细节。这篇文章的目的是向您简述预期的内容,以及如何理解它们。
  
  C# 8.0 新特性
  
  下面是 C# 8.0 中最重要的新特性的概述。还有一些较小的改进正在进行中,这些改进将在未来几个月逐渐显现出来。
  
  Nullable reference types 可空引用类型
  
  此特性的目的是帮助处理无处不在的空引用异常,这种异常已经困扰了半个世纪的面向对象编程。
  
  这个特性阻止您将 null 放入普通引用类型中(如字符串),从而使这些类型不可为 null!不过它是温和的提示警告,而不是错误。所以,它会让现有代码出现新的警告,因此您必须有选择的使用该功能 (您可以在项目、文件甚至行级别执行此操作)。
  
  string s = null; // Warning: Assignment of null to non-nullable reference type
  
  如果您确实想要 null 怎么办?可以使用一个可空引用类型,例如 string? 这样:
  
  string? s = null; // Ok
  
  当您尝试使用可空引用类型时,你首先需要检查是否为空。编译器会分析代码流,以查看 null 值是否可以将其用于当前位置:
  
  void M(string? s)
  
  {
  
  Console.WriteLine(s.Length); // Warning: Possible null reference exception
  
  if (s != null)
  
  {
  
  Console.WriteLine(s.Length); // Ok: You won't get here if s is null
  
  }
  
  }
  
  这个特性的要点是,C# 允许您表达“可空的意图”,并且在您不遵守它时候发出警告。
  
  Async streams 异步流
  
  C# 5.0 的 async/await 特性使您可以用非常简单的代码消费(或生产)异步结果, 而无需回调:
  
  async Task<int> GetBigResultAsync()
  
  {
  
  var result = await GetResultAsync();
  
  if (result > 20) return result;
  
  else return -1;
  
  }
  
  如果您想要消费(或生产)连续的结果流(例如您可能从物联网设备或云服务获得),则没有那么有用。 异步流就是为此而存在的。
  
  如果您想要消费(或生产)连续的结果流(例如您可能从物联网设备或云服务获得),则没有那么有用。 异步流就是为此而存在的。
  
  我们现在介绍一下您所期望的 IAsyncEnumerable<T>,即 IEnumerable<T> 的异步版本。允许您 await foreach 以消费它们的元素,并 yield return 以生产元素。
  
  async IAsyncEnumerable<int> GetBigResultsAsync()
  
  {
  
  await foreach (var result in GetResultsAsync())
  
  {
  
  if (result > 20) yield return result;
  
  }
  
  }
  
  Ranges and indices 范围和索引
  
  我们正在添加一个类型 Index,可用于索引。您可以创建一个整型来表示从头开始的索引,或者一个 ^ 前缀的从结尾表示的索引:
  
  Index i1 = 3;  // number 3 from beginning
  
  Index i2 = ^4; // number 4 from end
  
  int[] a = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
  
  Console.WriteLine($"{a[i1]}, {a[i2]}"); // "3, 6"
  
  我们还引入了一个 Range 类型,它由两个 Index 组成,一个用于开始,一个用于结束,并且可以用 x..y 这样的范围表达式来编写。然后,您可以使用 Range 进行索引来生成切片:
  
  var slice = a[i1..i2]; // { 3, 4, 5 }
  
  Default implementations of interface members 接口成员的默认实现
  
  现在,一旦你发布了一个接口,游戏就结束了:你不能在不破坏它的所有现有实现的情况下向它添加成员。
  
  在 C# 8.0 中,我们允许您为接口成员提供一个默认实现。因此,如果某人没有实现该成员(可能因为他们编写代码时还没有该成员),他们将只得到默认的实现。
  
  interface ILogger
  
  {
  
  void Log(LogLevel level, string message);
  
  void Log(Exception ex) => Log(LogLevel.Error, ex.ToString()); // New overload
  
  }
  
  class ConsoleLogger : ILogger
  
  {
  
  public void Log(LogLevel www.huarenyl.cn level, string message) { ... }
  
  // Log(Exception) gets default www.hjshidpt.com implementation
  
  }
  
  ConsoleLogger 类不必实现 ILogger 中 Log(www.dfgjpt.com Exception) 重载函数,因为它已经定义了默认实现。现在只要提供了一个默认实现,您就可以添加新的成员到已经存在的公开接口中了。
  
  Recursive 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 } 会检查 Person 是否是 Student,然后将常量模式 false 应用于 Graduated 属性以查看它们是否已毕业,并将模式字符串 name 添加到其 Name 属性中,得到他们的名字(如果非空)。因此,如果 p 是 Student,没有毕业并且具有非空的名字,则返回该名字。
  
  Switch expressions Switch 表达式
  
  带有模式的 switch 语句在 C# 7.0 中非常强大,但编写起来很麻烦。switch 表达式是一个“轻量级”版本,其中所有情况都是表达式:
  
  var area = figure switch
  
  {
  
  Line _      => 0,
  
  Rectangle r =www.furong157.com> r.Width * r.Height,
  
  Circle c    =www.michenggw.com/> c.Radius * 2.0 * Math.PI,
  
  _           =www.mengzhidu178.com> throw new UnknownFigureException(figure)
  
  };
  
  Target-typed new-expressions 已知目标类型的新表达式
  
  在许多情况下,当您创建新对象时,类型已经可以从上下文中知道。在这些情况下,可以省略类型:
  
  Point[] ps = { new (1, 4), new (3,-2), new (9, 5) }; // all Points
  
  该功能的实现由社区成员提供,谢谢!
  
  平台依赖性
  
  大多数 C# 8.0 语言特性都可以在任何版本的 .NET 上运行。但是,其中一些具有平台依赖性。
  
  Async streams, Index 和 Range 都依赖于 .NET Standard 2.1 的新类型。正如 Immo 在他的文章《公布.NET Standard 2.1》所说的那样,.NET Core 3.0 、Xamarin 、Unity 和 Mono 都将实现 .NET Standard 2.1,但 .NET Framework 4.8 不会。这意味着当您将 C# 8.0 指向到 .NET Framework 4.8 时,使用这些功能所需的类型将不可用。
  
  与往常一样,C# 编译器对它所依赖的类型非常宽容。如果它能找到具有正确的名字和形态的类型,则很乐意将它们作为目标。
  
  默认接口实现依赖于新的增强运行时,我们也不会在 .NET Runtime 4.8 中实现这些。因此,此特性不适用于 .NET Framework 4.8 和旧版本的 .NET。
  
  十余年间,为了保持运行时的稳定,我们无法在其中实现新的语言特性。随着现代化运行时的并行性和开源性,我们觉得可以负责任地去重新开发它们,并在考虑到这一点时进行语言设计。 Scott 在其 .NET Core 3.0 和 .NET Framework 4.8 更新中解释说,.NET Framework 将来会看到较少的创新,而是关注稳定性和可靠性。考虑到这一点,我们认为,直接忽略某些语言特性会好一些。
  
  想要了解更多?
  
  C# 语言的设计过程是开源的,在这个repo中。如果您不经常跟进,可能会有点混乱和力不从心。语言设计的核心是语言设计会议,记录在 C# 语言设计日记。
  
  大约一年前,我写了一篇介绍C#中的可空引用类型的文章。您仍然可以阅读它并得到一些信息。。
  
  您还可以观看视频,例如 Microsoft Build 2018 大会上的 C# 未来,或者 .NET Conf 2018 大会上的即将到来的 C#,它展示了其中一些特性。
  
  Kathleen 有一篇很好的帖子来阐述了 .Net Core 3.0 中的 Visual Basic 的计划。
  
  当我们开始将这些功能作为 Visual Studio 2019 预览版的一部分发布时,我们还将发布有关各个功能的更多详细信息。
  
  就个人而言,我迫不及待地要把它们交到你们所有人手中!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值