数学运算null
请解释为什么这个测试通过?数学运算null
[Test]
public void TestNullOps()
{
Assert.That(10/null, Is.Null);
Assert.That(10 * null, Is.Null);
Assert.That(10 + null, Is.Null);
Assert.That(10 - null, Is.Null);
Assert.That(10 % null, Is.Null);
Assert.That(null/10, Is.Null);
Assert.That(null * 10, Is.Null);
Assert.That(null + 10, Is.Null);
Assert.That(null - 10, Is.Null);
Assert.That(null % 10, Is.Null);
int zero = 0;
Assert.That(null/zero, Is.Null);
}
我不明白这段代码是如何编译的。
看起来像空数学表达式的每个数学表达式Nullable<T>
(例如10/null
是Nullable<int>
)。但我在Nullable<T>
类中没有看到运算符方法。如果这些操作符取自int
,为什么最后的断言不会失败?
从MSDN:
预定义的一元和二元运营商和用户定义的任何运营商存在值类型也可以通过空类型一起使用。如果操作数为null,则这些运算符产生一个空值;否则,操作员使用包含的值来计算结果。
这就是为什么所有测试都通过了,包括最后一个测试 - 无论操作数的值是多少,如果另一个操作数是null
,那么结果是null
。
Nullable<T>
的运营商是所谓的“提升”运营商; c#编译器将运算符用于T
并应用一组预定义的规则;例如对于+
,解除+
是null
如果任一操作数为空,否则为内部值的总和。回到最后;再次,如果任一操作数是null
- 它从不执行该划分被定义为null
。
难道是编译器只是把它翻译成别的东西吗?看到我的答案。 –
@Martin我已经评论过你的答案; p –
@MarcGravell如果除法从未执行,为什么编译器不编译'Assert.That(null/0,Is.Null);'? – altso
我假设编译器将zero
转换为Nullable<int>
,并提供了底层的除法运算符。由于Nullable
类型可能为空,因此在编译期间不会捕获除0。最好的猜测是,他们希望你能够在div/0发生的情况下进行空测试。
我想看到下面使用反射
var myValue = 10/null;
从代码生成的代码,编译器把它变成这样:
int? myValue = null;
而且这不会编译,所以你不能绝招吧:
是的,但是这只是重申了这个问题,因为在这两种情况下**都是编译器在执行此操作(使用相同的规则) - 简单地说,它恰好能够在此情况下将其作为常量值进行操作。 –
是的,感谢关于常量的建议。 – altso
请注意'=='在这里有稍微不同的规则;如果* both *为空,则它是'true' –
是的,就我所知,对于'!='也是如此 - 如果一个是空的,另一个不是,那么结果是“真”。 – Andrei