请解释为什么这个测试通过了?
[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);
}
我不明白这段代码是如何编译的。
看起来每个带有null的数学表达式返回Nullable<T>
(例如10 / null
是Nullable<int>
)。但是我没有在Nullable<T>
类中看到运算符方法。如果这些运算符取自int
,为什么最后一个断言不会失败?
答案 0 :(得分:37)
来自MSDN:
预定义的一元和二元运算符以及值类型存在的任何用户定义的运算符也可以由可空类型使用。如果操作数为null,则这些运算符产生空值;否则,运算符使用包含的值来计算结果。
这就是为什么所有测试都通过了,包括最后一个 - 无论操作数值是什么,如果另一个操作数是null
,那么结果是null
。
答案 1 :(得分:16)
Nullable<T>
的运算符是所谓的“提升”运算符]; c#编译器获取T
可用的运算符并应用一组预定义的规则;例如,对于+
,如果任一操作数为null,则提升的+
为null
,否则为内部值的总和。最后一个;再次,如果任一操作数为null
,则除法定义为null
- 它永远执行除法。
答案 2 :(得分:2)
我尝试使用反射器
查看下面代码中生成的代码var myValue = 10 / null;
编译器把它变成了这个:
int? myValue = null;
这不会编译,所以你不能欺骗它:
object myNull = null;
var myValue = 10 / myNull;
答案 3 :(得分:1)
我认为编译器会将zero
转换为Nullable<int>
,并提供底层的除法运算符。由于Nullable
类型可能为null,因此在编译期间不会捕获除以0。最好的猜测是,他们希望您能够在发生div / 0的情况下进行空值测试。
答案 4 :(得分:1)
此列表中的操作始终返回NULL:
1 + 2 + 3 + NULL
5 * NULL - 7
'Home ' || 'sweet ' || NULL
MyField = NULL
MyField <> NULL
NULL = NULL