C# 带null的数学运算

C# 带null的数学运算,c#,C#,请解释一下为什么这次考试通过 [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

请解释一下为什么这次考试通过

[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的数学表达式都返回
null
(例如
10/null
是一个
null
)。但是我在
Nullable
类中没有看到运算符方法。如果这些运算符取自
int
,为什么最后一个断言没有失败?

可为空的
运算符是所谓的“提升”运算符];c#编译器获取可用于
T
的运算符,并应用一组预定义的规则;例如,对于
+
,如果任一操作数为null,则提升的
+
null
,否则为内部值之和。你是最后一个;同样,如果任一操作数为
null
,则除法定义为
null
——它从不执行除法。

我假设编译器将
zero
转换为
null
,并提供底层除法运算符。由于
Nullable
类型可能为null,因此在编译期间不会捕获被0除的情况。最好的猜测是,他们希望您能够在发生div/0的情况下执行空测试。

来自:

可空类型也可以使用预定义的一元运算符和二元运算符以及存在于值类型中的任何用户定义运算符。如果操作数为空,这些运算符将生成空值;否则,运算符将使用包含的值来计算结果


这就是为什么所有测试都通过了,包括最后一个测试-无论操作数值是什么,如果另一个操作数是
null
,那么结果是
null

,我尝试使用reflector从下面的代码中查看生成的代码

var myValue = 10 / null;
编译器将其转换为:

int? myValue = null;
这是无法编译的,所以你不能欺骗它:

object myNull = null;
var myValue = 10 / myNull;

此列表中的操作始终返回空值:

1 + 2 + 3 + NULL

5 * NULL - 7

'Home ' || 'sweet ' || NULL

MyField = NULL

MyField <> NULL

NULL = NULL
1+2+3+NULL
5*NULL-7
“Home”| |“sweet”| |空
MyField=NULL
MyField NULL
空=空

注意,
==
在这里有一些不同的规则;如果两者都为空,则为
是,而
也是如此=据我所知-如果一个为null,另一个为null,则结果为
true
。另一个注释是,比较运算符(
=
)不返回可为null的值;如果其中一个或两个操作数都为null,它们只返回false。是否编译器只是将其转换为其他内容?请看我的答案。@marcGravel如果从未执行除法,为什么编译器不编译
Assert.That(null/0,is.null)?@altso-我很困惑;您声明了“为什么最后一个断言没有失败”-事实上,它没有失败(AFAIK)-
null/0
null
@MarcGravel在帖子中的断言和我的评论之间有区别。在注释中,零是一个常量。编译器在这方面失败了。是的,但这只是重申了问题,因为在这两种情况下,编译器都在这样做(使用相同的规则)-简单地说,在这种情况下,它恰好能够作为常量值来做。请注意,不鼓励只使用链接的答案(链接往往会随着时间的推移而过时)。请考虑编辑你的答案并在这里添加一个概要。这是什么语言?这是针对general@Sam的。这是一个不相关的答案——这是关于SQL,而不是C。(你应该把这个链接作为答案的一部分——可以看出这个链接是关于Firebird SQL server的。)