AICon 上海站|90%日程已就绪,解锁Al未来! 了解详情
写点什么

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:174714
用户头像

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

关注

评论

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

推荐8个提高工作效率的IntelliJ插件

JAVA旭阳

Java IDEA

低代码为什么会受到企业青睐?是何原因?

优秀

低代码

VUCA时代下的产品创新方法论(上)

Jackchang234987

VUCA 产品创新

使用brew安装历史版本的几种方式

Geek_pwdeic

macos homebrew

2022-12-20:二狗买了一些小兵玩具,和大胖一起玩, 一共有n个小兵,这n个小兵拍成一列, 第i个小兵战斗力为hi,然后他们两个开始对小兵进行排列, 一共进行m次操作,二狗每次操作选择一个数k,

福大大架构师每日一题

算法 rust 福大大

汽车行业:充分借力数据价值,推动数字化营销链路闭环

HarmonyOS SDK

HMS Core

【开源项目】今天推荐一个很好的开源项目,一款新的编程语言——HVML

hvmlenvoy

GitHub 编程语言 开源项目

本年度软件供应链攻击事件回顾

SEAL安全

基础设施 第三方风险 软件供应链安全 软件供应链攻击 12 月 PK 榜

Celestia 简介:重新构想的区块链

devpoint

区块链 以太坊 12月月更 Celestia

ZBC成功上线PancakeSwap的糖浆池,并有望在不久上线Binance

股市老人

RayLink 远控软件又推出 2 个重磅宝藏功能免费用

RayLink远程工具

远程控制软件 远程办公软件 远控软件

如何构建企业内的 TiDB 自运维体系

得物技术

数据库 运维 TiDB TiDB 底层架构 12 月 PK 榜

Verilog的模块与端口

芯动大师

Verilog Verilog语法 Verilog模块端口

直播预约|阿里云EMR 2.0 重磅发布

阿里云大数据AI技术

大数据 阿里云 大数据 开源

传统企业DevOps基础设施架构规划之道

冯文辉

DevOps 华为云DevCloud 华为CodeArts

“唤醒”大数据价值,敏捷数据开发成为企业数字化发展的法宝

数造万象

云渲染怎么收费??云渲染一张图多少钱?

Renderbus瑞云渲染农场

云渲染 云渲染平台

架构实战营 3-2 架构设计前期随堂练习

西山薄凉

「架构实战营」

ZBC成功上线PancakeSwap的糖浆池,并有望在不久上线Binance

鳄鱼视界

Gradle基础操作一

派大星

Gradle

专访实在智能孙林君:颠覆传统RPA的实在IPA模式如何做到真正人人可用

王吉伟频道

RPA 机器人流程自动化 实在智能 实在IPA模式 RPA人人可用

企业常用shell脚本汇总

@下一站

企业运维 12月日更 12月月更 shell脚本 脚本程序

跨平台应用开发进阶(三十):uni-app 实现集成火山视频直播服务

No Silver Bullet

uni-app 12月月更 服务集成 火山视频直播服务

跨平台应用开发进阶(三十一) :uni-app实现覆盖原生控件导航栏和tabbar全屏弹窗

No Silver Bullet

uni-app 跨平台应用 12月月更 原生控件覆盖 全屏弹窗

HarmonyOS 3优化游戏续航,nova 6等老机型升级后游戏续航更持久

极客天地

架构实战营 3-3 架构设计中期随堂练习

西山薄凉

「架构实战营」

Dubbo架构设计与源码解析(二) 服务注册

京东科技开发者

架构 dubbo spi 服务注册 Dubbo SPI

YonBuilder移动开发平台AVM框架封装数据表格组件

YonBuilder低代码开发平台

开发者 前端 AVM

跨平台应用开发进阶(三十二) :AK/SK鉴权原理简介

No Silver Bullet

uni-app 12月月更 AK/SK鉴权

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