NVIDIA 初创加速计划,免费加速您的创业启动 了解详情
写点什么

C# 7.3 新特性一览

  • 2018-05-23
  • 本文字数:2272 字

    阅读完需:约 7 分钟

看新闻很累?看技术新闻更累?试试下载 InfoQ 手机客户端,每天上下班路上听新闻,有趣还有料!

通过一个相对较小的版本,C# 7.3 解决了一些自 C# 1 和 2 以来长期悬而未决的问题。

重载解析

从 C# 1.0 开始,重载解析规则的设计就相当有问题。在某些情况下,它会选两个或更多方法作为候选,虽然所有这些方法中只有一个会被使用。根据这些错误选出的方法的优先级,编辑器要么会报没有匹配的方法,要么会报匹配不明确。

C# 7.3 把其中部分检查移到了重载解析期间,而不是重载解析之后,这样,错误的匹配就不会导致编译器错误。改进后的重载候选提案概括了这些检查:

  1. 当一个方法组既包含实例又包含静态成员时,如果调用时没有实例接收者或上下文,我们就会丢弃实例成员,如果调用时有实例接收者,我们就丢弃静态成员。当没有接收者时,我们只会在一个静态上下文中包含静态成员,否则会同时包含静态和实例成员。当不确定接收者是实例还是类型时,考虑到 color-color 的情况,我们会两者都包含。在静态上下文中,不能使用隐式的 this 实例接收者,它包含的方法体中没有定义 this,如静态成员,它还包含不能使用 this 的地方,如字段初始化器和构造函数初始化器。
  2. 当方法组包含一些泛型方法,而它们的类型参数不满足约束时,这些成员会被从候选集中移除。
  3. 对于方法组转换,那些返回类型与委托的返回类型不一致的候选方法会被从候选集中移除。

泛型约束:枚举、委托和非托管

自 C# 2.0 引入泛型以来,开发人员就一直在抱怨,无法把一个泛型类型指定为枚举。这个问题终于解决了,你现在可以使用 enum 关键字作为泛型约束了。同样,你现在可以使用 delegate 关键字作为泛型约束了。

这些关键字可能并不是和你预期的那样发挥作用。如果约束是 T : enum,那么有人可能就会使用 Foo,而你的意思也许是让他们使用 System.Enum 的子类。尽管如此,这应该可以覆盖枚举和委托的大多数使用场景。

非托管类型约束提案使用了 unmanaged 关键字,用于说明泛型类型必须是“非引用类型,并且在任意嵌套层次上都不包含引用类型字段。”这是为了用在底层交互代码中,当你需要“创建可供所有非托管类型重用的例程时”。非托管类型包括:

  • 基元类型 sbyte、byte、short、ushort、int、uint、long、ulong、char、float、double、decimal、bool、IntPtr 或 UIntPtr;
  • 任何枚举类型;
  • 指针类型
  • 只包含上述类型的用户定义结构。

隐藏字段的 Attribute

虽然自实现的 Property 非常有用,但是它们有一些局限,Attribute 不适用于后备字段,因为你看不到它。虽然通常来说这不是问题,但在处理序列化时就可能有问题了。

面向自实现Property 字段的Attribute 提案用一种简单的方法解决了这个问题。当把一个Attribute 应用到一个自实现的Property 时,只需在字段定义时加上field: 修饰符。

复制代码
[Serializable]
public class Foo {
[field: NonSerialized]
public string MySecret { get; set; }
}

元组比较(== 和!=)

虽然提案的名称“支持元组类型 == 和!= 比较”很好地概括了这项特性,但还有一些细节和边际情况需要注意。最重要的是潜在的破坏性变化:

如果有人自己编写了一个 ValueTuple 类型,并实现了比较操作符,之前,重载解析会找到它们。但是,新的元组情况出现在重载解析之前,我们会通过元组比较处理这种情况,而不是基于用户定义的比较。

理想情况下, 这个自定义的 ValueTuple 类型会遵循与 C# 7.3 编译器同样的规则,但是,在如何处理嵌套元组和动态类型方面,可能会有微妙的差别。

初始化器中的表达式变量

在某种程度上,这看上去像个反特性。微软不仅没有增加功能,而是去掉了表达式变量的使用场景限制。

我们移除了在 ctor 初始化器中不能声明表达式变量(out 变量声明和声明方式)的限制。这样声明的变量其作用域是整个构造函数的函数体。

我们移除了在字段或 Property 初始化器中不能声明表达式变量(out 变量声明和声明方式)的限制。这样声明的变量其作用域是整个初始化表达式。

我们移除了在会被翻译成 lambda 表达式主体的查询表达式子句中不能声明表达式变量(out 变量声明和声明方式)的限制。这样声明的变量其作用域是整个查询子句表达式。

最初增加这些限制只是因为“没有时间”。也许,这些限制缩短了了 C# 7 之前版本完工所需的测试时间。

栈分配数组

C#中有一个很少使用单相当重要的特性,就是能够通过 stackalloc 关键字在栈上分配数组。与分配在堆上、会导致 GC 压力的普通数组相比,这可能会提供更好的性能。

复制代码
int* block = stackalloc int[3] { 1, 2, 3 };

使用栈分配数组有点危险。因为它需要持有一个指向栈的指针,而且只能用于不安全的上下文中。CLR 会启用缓冲区溢出检测来缓解这种情况,那会导致“应用程序尽快终止”。

在 C# 7.3 中,你可以在创建数组时对其初始化,就像你对普通数组所做的那样。该提案没有提供细节,但微软正考虑预初始化一个主数组,当函数被调用时可以快速复制。理论上讲,这比创建一个数组然后一个元素一个元素的初始化要快。

注意,栈分配数组适用于需要大量小数组供短暂使用的场景。不能把它用于大数组或者深度递归函数,因为那可能会超出可用的栈空间。

栈分配Span

栈分配数组的一个安全替代方案是栈分配Span。消除指针,也就消除了缓冲区溢出的可能性。反过来,这意味着你可以使用它而不必把方法标记为不安全的。

复制代码
Span<int> block = stackalloc int[3] { 1, 2, 3 };

注意,Span 依赖于 NuGet 包 System.Memory。

可重新赋值的 Ref 局部变量

Ref 局部变量现在可以和普通局部变量一样重新赋值了。

要了解其他C# 7.3 提案,请查阅C#语言的GitHub 站点。

查看英文原文 New Features in C# 7.3

2018-05-23 15:174185
用户头像

发布了 1008 篇内容, 共 374.6 次阅读, 收获喜欢 341 次。

关注

评论

发布
暂无评论
发现更多内容

码农理财(二)

北漂码农有话说

Review week1: Amazon的领导力法则

猫吃小怪兽

学习 高效工作 程序员 个人成长

《从0到1学习Flink》—— Apache Flink 介绍

zhisheng

大数据 flink 流计算

《从0到1学习Flink》—— Flink 写入数据到 Kafka

zhisheng

大数据 flink 流计算

要弄清楚if/switch的本质区别,以及优化方式

张驰

Java

ARTS 第 51 周

马克图布

ARTS 打卡计划

【迁移】CQRS很难吗?(译文:底部有原文地址)

罗琦

领域驱动设计 DDD

《从0到1学习Flink》—— 介绍Flink中的Stream Windows

zhisheng

大数据 flink 流计算

《从0到1学习Flink》—— Flink 读取 Kafka 数据写入到 RabbitMQ

zhisheng

大数据 flink 流计算

python 实现·十大排序算法之选择排序(Selection Sort)

南风以南

Python 排序算法

《从0到1学习Flink》—— 如何自定义 Data Source ?

zhisheng

大数据 flink 流计算

《从0到1学习Flink》—— Flink 中几种 Time 详解

zhisheng

大数据 flink 流计算

《从0到1学习Flink》—— Flink 项目如何运行?

zhisheng

大数据 flink 流计算

《从0到1学习Flink》—— Flink 写入数据到 ElasticSearch

zhisheng

大数据 flink 流计算

极客时间的三种身份:碎片整合的大师、成长焦虑的救星、工作技能的提升站

大橘栗

《从0到1学习Flink》—— Flink 配置文件详解

zhisheng

大数据 flink 流计算

《从0到1学习Flink》—— Data Sink 介绍

zhisheng

大数据 flink 流计算

【迁移】读完了GFS论文之后的感悟

罗琦

大数据 GFS 论文阅读

《从0到1学习Flink》—— Flink JobManager 高可用性配置

zhisheng

大数据 flink 流计算

《从0到1学习Flink》—— Mac 上搭建 Flink 1.6.0 环境并构建运行简单程序入门

zhisheng

大数据 flink 流计算

【迁移】Flink vs Spark

罗琦

大数据 flink spark

《从0到1学习Flink》—— Data Source 介绍

zhisheng

大数据 flink 流计算

《从0到1学习Flink》—— Flink Data transformation(转换)

zhisheng

大数据 flink 流计算

《从0到1学习Flink》—— Flink 读取 Kafka 数据批量写入到 MySQL

zhisheng

大数据 flink 流计算

你没必要活的那么累

小天同学

深度思考 个人成长 生活 成长 感悟

图文并茂讲述如何正确的使用缓存

小趴菜~

缓存 后端 缓存穿透 缓存击穿 缓存雪崩

写给产品经理的信(1):产品经理的经济基础逻辑思维能力

punkboy

产品经理 产品设计 职业规划 逻辑思维 工作

勇攀监控高峰-EMonitor之根因分析

乒乓狂魔

监控 全链路监控 故障定位 根因分析 AIOPS

【迁移】撸论文系列之——Bigtable

罗琦

论文阅读 bigtable

【迁移】用Redlock构建Redis分布式锁【译】

罗琦

分布式锁

《从0到1学习Flink》—— 如何自定义 Data Sink ?

zhisheng

大数据 flink 流计算

C# 7.3新特性一览_.NET_Jonathan Allen_InfoQ精选文章