文档结构  
翻译进度:已翻译     翻译赏金:0 元 (?)    ¥ 我要打赏

这是一篇关于C#语言规范变化的故事。

规范的改变是因为1.0版本的C#规范推翻了自己,其中的一个地方是不正确的并且打破了一个特性。

这个变化出现在“条件逻辑运算符”部分。在第1版的规范中规定:

  • x && y 运算等同于 x & y 运算,但仅当x为true时才会判断y。
  • x || y 运算等同于 x | y  运算, 但仅当x为false时才会判断y 。

后来的版本(从第3版开始)规定:

  • x && y 运算等同于 x & y 运算, 但仅当x为not false时才会判断y 。
  • x || y 运算等同于 x | y 运算, 但仅当x为not true时才会判断y 。
第 1 段(可获 2 积分)

为什么会有这样的改变呢?

在其后的几部分中,规范定义了“用户定义的条件逻辑运算符”。 C#语言不允许你创建一个用户定义的 && 运算符 或 || 运算符。相反,你必须定义 | 运算符,& 运算符,true运算符和false运算符。以下是相关的文本:

&& 和 || 运算是通过将用户定义的true运算符或false运算符与选定的用户定义的运算符组合在一起来判断的:

  • x && y  运算按 T.false(x) ? x : T.&(x,y) 进行计算,……换句话说,首先计算x,然后对结果调用false运算符以确定x是否一定为假。如果x一定为假,则运算结果为之前计算过的x的值。否则将计算y,并用之前计算的x的值和y的值去调用选定的 & 运算符以得出运算结果。
  • x || y 运算按 T.true(x) ? x : T.|(x,y)  进行计算……换句话说,首先计算x,然后对结果调用true运算符以确定x是否一定为真。如果x一定为真,则运算结果为之前计算过的x的值。否则将计算y,并用之前计算的x的值和y的值去调用选定的 | 运算符以得出运算结果。

这里的关键点是,对于 && 运算符要检查x并确保它不为假,而对于 || 运算符要检查x并确保它不为真。

第 2 段(可获 2 积分)

规范为什么必须改变

1.0版本的规范有着严重的局限性。由用户自定义类型(User Defined Types)定义的 & 运算符或 | 运算符当且仅当在被定义的true运算符和false运算符其中有一个始终为真时工作。

语言中没有给出明确的规定。

思考练习,假设在某些描述中你有一个也许既不是true也不是false的类型。也许他们的范围在“真”、“假”和“既非真也非假”之间。

如果你想要一个具体的例子,考虑一下单字节类型的字段。当所有位均为1时,true运算符将返回真。当所有位均为0时,false运算符将返回真。在各种情况下,判断 ‘x && y’  或者 ‘x || y’  运算时均需要用到左右两侧的运算符。在这里短路法是行不通的。

这就是为什么规范在第3板做出了改变。

第 3 段(可获 2 积分)

在规范中的更多解释

我们觉得关于改变,规范需要给出更多的解释。在ECMA第5版中,我们添加了这些备注:

注:短路法使用'not true'和'not false'条件的原因是当短路法适用时才启用用户自定义条件运算符。用户自定义类型(User Defined Types)可用来描述什么情况下true运算符返回假,什么情况下false运算符返回假。在这些情况中,&& 或 || 运算也不能使用短路法。

在C#规范中(值得庆幸的是)推翻自己的情况相对比较少。但是在大规模的文档中,却很容易混入这种情况。每当我们发现时,就会去审查并纠正他们。

第 4 段(可获 2 积分)

文章评论