C# 7.1、7.2特性追踪
作为Visual Studio 15.3的一部分,微软发布了自.NET 1.1以来C#的第一个单点版本。C# 7.1提供了三个新特性,其中有两个是成功有效的。
C# 7.1/7.2:default字面量
default
字面量旨在减少一些样板代码。下面是一个常见的例子:
public Task<Order> GetOrderAsync(int orderKey, CancellationToken token = default(CancellationToken))
这多少有点啰嗦,因此,模仿Visual Basic的Nothing
关键字,上述代码可以写成下面这样:
public Task<Order> GetOrderAsync(int orderKey, CancellationToken token = default)
这行代码可以按照预期方式运行。但是,当使用一个可空的值类型时,问题就来了。
public Task<Order> GetOrders(int? limit = default)
这行代码应该把limit
参数置为空,但在C# 7.1中,它实际返回0。
这个问题的修复计划在C# 7.2中进行,该版本会随Visual Studio 15.5一起发布。
C# 7.1:元组名称推断
自从引入了匿名类型,C#就可以隐式命名属性。例如,在下面这行代码中,对象y
会拥有名为A
和B
的属性。
var y = new { x.A, x.B };
在C# 7.1中,值元组也具有这个特性。
var z1 = (A: x.A, B: x.B); //显式名称 var z2 = (x.A, x.B); //推断名称
要了解更多有关元组名称推断的信息,请看下我们之前的报道。
C# 7.1:Async Main
这里没有多少可说的。Main函数现在可以异步执行,这减少了之前需要编写的一些样板代码。
C# 7.2:条件Ref
C#的条件操作符通常被称为“三元运算符”,因为这是这门语言中的唯一一个。C# 7.2将会提供第二个三元操作符,名为条件Ref操作符。
这个小特性让开发人员可以在条件中使用ref
表达式。下面是提案中的一个例子:
ref var r = ref (arr != null ? ref arr[0]: ref otherArr[0]);
注意,除了在靠近两种可能结果的地方需要使用ref
关键字外,在包含整个表达式的括号外也需要使用ref
关键字。
C# 7.2:起始分隔符
该特性扩展了在数值字面量中使用下划线的能力。下面的示例摘自提案:
123 // C# 1.0及更高版本可用 1_2_3 // C# 7.0及更高版本可用 0x1_2_3 // C# 7.0及更高版本可用 0b101 // C# 7.0新增的二进制字面量 0b1_0_1 // C# 7.0及更高版本可用 // 在C# 7.2中,_可以用在`0x`或`0b`之后 0x_1_2 // C# 7.2及更高版本可用 0b_1_0_1 // C# 7.2及更高版本可用
C# 7.2:非尾部命名参数
C#中的命名参数服务于两种目的:
- 允许跳过可选参数;
- 明确访问接口,尤其是
Boolean
参数。
该特性处理第二种情况。例如:
void DoSomething(bool delayExecution, bool continueOnError, int maxRecords); DoSomething(true, false, 100);
除非开发人员记住了函数签名,否则很难一眼就看出了true
和false
对应什么。过去,开发人员可以写成下面这样:
DoSomething(delayExecution: true, continueOnError: false, maxRecords: 100);
但是,如果对maxRecords
参数没有疑问却还需要指定似乎就有点奇怪。在非尾部命名参数提案中,开发人员可以根据需要指定参数。
DoSomething(delayExecution: true, continueOnError: false, 100);
编者注:当清晰度成为问题时,Enum
仍然好于Boolean
。
C# 7.2:Private Protected
C#有5个访问级别:private
、internal
、protected
、protected
或internal
、public
。但是,CLR还有第六个访问级别,名为FamANDAssem
,“允许程序集中的子类型访问”。
冷知识:在CLR中,protected
称为family
,而internal
称为assembly
。
借助新关键字“private protected
”,开发人员可以使用CLR的FamANDAssem
标识了。Private Protected提案说明了这样做的重要性:
在许多情况下,API都会包含一些成员函数,只打算让提供该类型的程序集中的子类实现并使用。CLR提供了用于此目的的访问级别,但C#中没有。因此,别无选择,API所有者要么诉诸于internal
保护、自律或自定义分析器,要么使用protected
,并提供额外的文档说明,虽然该类型的公开文档中有这个成员函数,但它并不是公有API的一部分。至于后者的例子,可以看下Roslyn CSharpCompilationOptions
中以Common开头的成员。
C# 7.2:只读引用
我们之前报道过只读引用,所以这里没什么新东西要介绍。本质上讲,只读引用只是为了说明开发人员希望通过引用传递结构从而获得性能收益,而不是真正改变值的能力。
目前,只读引用提案尚处于原型阶段,还没有实现。
ref-like类型编译时安全强化[7.2提案]
该C#特性又称为“内部指针”或“ref-like
类型”。该提案旨在让编译器可以要求特定的类型(Span<T>
)仅出现在栈上。该特性仅对高性能场景而言比较重要。从我们上次报道以来,ref-like类型提案没有任何变化。
放弃的特性
以下特性没有被标记为7.2提案的一部分。虽然这不是说一定不会标记,但可能不会很快发生。