微软 C#语言的项目经理 Mads Torgersen,最近提议在C# 7 中引入可为选项类型(option types)的引用类型。加入选项类型能让C#语言变得更安全,正如Torgersen 所说,在C#里,因为任一引用类型都能引用一个空值,从而导致了空引用异常的泛滥成灾,而使用选项类型能减少空引用异常的产生。
C#已经对 nullable 值类型提供了支持,即对基于 struct 的已提供了支持,但不支持基于 class 的引用类型。对一门现存的已然成熟的编程语言事后加入选项类型,这其中存在着巨大的复杂性,出于这一原因,Torgersen 不打算建立一套“滴水不漏的”机制,而是在检测到代码可能存在解引用空值的时候发出警告信息。
新的提议方案对一个现有的引用类型 T 有如下约定:
- T 用来表示一个非 nullable 类型;
- T? 用来表示一个 nullable 引用类型;
- 在以下情况下,编译器将发出告警信息:
- 一个 nullable 的
T? 类型被解引用或者转化为一个非
nullable 类型; - 将 null/default(T) 赋值给非 nullable T 类型变量;
- 流分析检测到一个 nullable 引用很可能不再是空值;
- 构造函数在返回前未对非 nullable 引用进行赋值;
- 构造函数使用尚未赋值的非 nullable 引用。
- 一个 nullable 的
另一方面,当一个非 nullable 数组在进行初始化时,无法确保其中为 null 的数组成员不被保留下来。
使用空条件操作符( null-conditional operator )?.,可参考介绍 C# 6 ,将产生以下效果:
string s; string? ns = SomeStringMaybe(); s = ns; // emits warning if (ns != null) { s = ns; } // ok WriteLine(ns.Length); // emits warning WriteLine(ns?.Length); // ok
尽管使用这种新设计出的方法不用改动任何的现有代码,但该方法仍可能对编译器的行为产生潜在的影响,因为在当前的 C#里,T 实际上用来表示一个 nullable 类型。因此,Torgersen 说,需要另外再新增一套机制来关闭告警信息,用于确保在跨 C#版本和程序集下的编译兼容性。
需要重点声明的是,当所赋的值为 null 时,若编译器只产生告警信息,那么 C# 7 仍将会允许一个非 nullable 类型 T 包含 null 类型,这主要是出于对程序集兼容性的考虑。这也使得C# 7 表现得与其他编程语言大相径庭,比如 Swift option types 和 Haskell Maybe ,在 Swift 和 Haskell 中,选项类型可被视为对基本类型的一种封装(实际上,在 Swift 里选项类型就是泛型类型,在 Haskell 里就是 monad)。
从通告的评论来看,人们对微软的提议反应不一。有些人担心在重新定义了类型 T 为非 nullable 之后,现存的 C#代码会产生大量的对他们来说毫无意义的告警信息。还有些人认为应该用 T! 或者其他不同于基本类型 T 的表示方式来表征非 nullable 类型,基本类型 T 继续用来表示 nullable 类型。微软的提议方法没有让任何已有的代码受益,应对其进行重构以使其有助于代码的 non-nullability。另外有部分人支持该提议,并表示自己更喜欢这种“严谨的”模式,在这种模式下,空值经由 option
查看英文原文: A Proposal to Add Option Types for References to C# 7
活动推荐:
2023年9月3-5日,「QCon全球软件开发大会·北京站」 将在北京•富力万丽酒店举办。此次大会以「启航·AIGC软件工程变革」为主题,策划了大前端融合提效、大模型应用落地、面向 AI 的存储、AIGC 浪潮下的研发效能提升、LLMOps、异构算力、微服务架构治理、业务安全技术、构建未来软件的编程语言、FinOps 等近30个精彩专题。咨询购票可联系票务经理 18514549229(微信同手机号)。
评论