BT

如何利用碎片时间提升技术认知与能力? 点击获取答案

C# 7.2和8.0路线图

| 作者 Jonathan Allen 关注 615 他的粉丝 ,译者 罗远航 关注  他的粉丝 发布于 2017年6月22日. 估计阅读时间: 6 分钟 | QCon上海2018 关注大数据平台技术选型、搭建、系统迁移和优化的经验。

C# 7.2和8.0的许多新功能已经列入了计划,其中包括空引用类型和有限形式的多重继承。

只读引用和只读结构体 [7.2原型]

首先提到的是只读引用和结构体。简单来讲,这项特性使得C#能够使用类似const的参数来提高性能。像我们所知道的“ref只读参数”和简单的“in参数”,这些特性使得大的结构体能够通过引用来进行传递,并且不允许对其进行修改。

这个提案中的一部分就是只读结构体。开发人员将一个结构体标记为只读之后,表示任何方法都不能对这个结构体进行修改。这会对性能有很大提升,因为它会告诉编译器,它可以跳过通常用于防止意外修改只读变量的复制操作。

Blittable类型 [7.2提案]

维基百科上是这样描述blittable类型的:

在微软的.NET框架中,数据在托管代码和非托管代码中的内存表示是截然不同的。然而,blittable类型被定义为在这两种不同的环境下,数据在内存中的表示是完全相同的,并且可以直接共享。

Non-blittable类型包括Boolean、string、char以及所有的引用类型。如果一个结构体包含了其中的一种类型,那么这个结构体本身也是non-blittable的。

目前,C#编译器通过检查一个类型的结构来推断它是否是blittable的。这在过去引发了一些问题,因为有时增加一个新的字段会使得一个blittable类型变成non-blittable,然而在某些情况下,这种变化是致命的。

Blittable类型提案中提到,使用关键字“blittable”能够明确地将一个结构体定义为blittable的。如果之后它的类型被修改为non-blittable的,编译器就会报错。

为了保证长期的向后兼容性,被定义为blittable的结构中只能包含同样明确定义为blittable的结构。此外,结构中不能使用StructLayout(LayoutKind.Auto)]。它表示的是结构体在物理内存中的排列方式。Explicit layout和sequential layout都是可以使用的。

注意:能够修改一个结构体的LayoutKind或者Pack被认为是一个突破性的改进,因为它改善了非托管代码访问结构体的方式。

Microsoft担心这个特性的过渡期。低层的类库必须采用明确的blittable类型,更高层的类库才能使用它们。

ref-like类型编译期安全增强 [7.2提案]

这个特性也叫做“interior pointer”或者“类ref类型(ref-like types)”。该提案允许编译器要求只能有特定的类型出现在栈上,比如Span<T>。其中列举了如下几个原因:

  1. Span<T>在语义上表示的是一个包含了一个引用和一个范围的结构体(ref T data, int length)。不管它的实现是怎样的,对这种类型的结构体的写入操作并不是原子的。并发地对这个结构进行“撕裂(tearing)”可能会导致它的长度和数据不匹配,有可能会引起超出访问范围(out-of-range)和类型不安全,这最终可能会导致GC时的堆崩溃,尽管代码看起来似乎是“安全”的。
  2. 在一些Span<T>的实现中,它的字段中会包含一个托管指针(managed pointer)。托管指针不支持堆对象的字段,并且将托管指针指向放在GC堆上的代码会在JIT(Just-in-time)期间崩溃。
  3. Span<T>允许引用局部堆栈帧中的数据:单独的局部变量或者栈上分配的数组。当Span<T>的实例的生命周期超过了引用的数据时,这会导致未定义的行为,包括类型安全违规和堆崩溃。

ref-like类型有如下几种使用限制:

  • ref-like类型不能作为数组的元素
  • ref-like类型不能用作泛型类型参数
  • ref-like变量不能被装箱
  • ref-like类型不能作为普通的非ref-like类型的字段
  • 一些间接限制,例如不允许在异步方法中使用ref-like类型,异步方法不支持ref-like类型字段

事实上,这意味着ref-like类型仅能被用作参数、局部变量以及某些情况下的返回值。ref-like类型能够包含另一个ref-like类型。

所有的ref-like类型都是只读结构体(详见上方描述)。

像ref类型一样,ref-like类型最终可能会成为“单赋值(single-assignment)”类型。该提案也提到了其他保障安全的方法,但是这个方法对编译器的负担是最小的。

C# 8.0原型

C# 8的两个新特性已经到达了原型阶段:

查看英文原文C# 7.2 and 8.0 Roadmap


感谢Mister Who对本文的审校。

给InfoQ中文站投稿或者参与内容翻译工作,请邮件至editors@cn.infoq.com。也欢迎大家通过新浪微博(@InfoQ@丁晓昀),微信(微信号:InfoQChina)关注我们。

评价本文

专业度
风格

您好,朋友!

您需要 注册一个InfoQ账号 或者 才能进行评论。在您完成注册后还需要进行一些设置。

获得来自InfoQ的更多体验。

告诉我们您的想法

允许的HTML标签: a,b,br,blockquote,i,li,pre,u,ul,p

当有人回复此评论时请E-mail通知我
社区评论

允许的HTML标签: a,b,br,blockquote,i,li,pre,u,ul,p

当有人回复此评论时请E-mail通知我

允许的HTML标签: a,b,br,blockquote,i,li,pre,u,ul,p

当有人回复此评论时请E-mail通知我

讨论

登陆InfoQ,与你最关心的话题互动。


找回密码....

Follow

关注你最喜爱的话题和作者

快速浏览网站内你所感兴趣话题的精选内容。

Like

内容自由定制

选择想要阅读的主题和喜爱的作者定制自己的新闻源。

Notifications

获取更新

设置通知机制以获取内容更新对您而言是否重要

BT