在这种情况下,为什么可空类型不相等?

时间:2009-04-24 11:30:16

标签: c# null

令人惊讶的是,下面的代码不会成功。

int? n1 = null;
int? n2 = null;
Assert.IsTrue(n1 <= n2);  // Fails here

你知道为什么吗?

4 个答案:

答案 0 :(得分:6)

在C#(和VB.Net)中使用具有空可空值的布尔逻辑通常会违反逻辑。我发现理解它的最好方法是记住“null不是一个值”。因为null不是值,所以无法对其执行任何操作。因此,“1 > null”和“1 < null”之类的内容都是正确的。

以下是详细指南:http://msdn.microsoft.com/en-us/library/2cf62fcy.aspx

如果您确实希望将null视为值,则可以使用GetValueOrDefaultMethod()将null与默认值相等。例如

Assert.IsTrue(n1.GetValueOrDefault() <= n2.GetValueOrDefault());  // True

这有点冗长,但它会完成工作。

答案 1 :(得分:4)

这是一个拼写错误,你的意思是“==”而不是“&lt; =”或者你误解了空值是如何工作的。

在几乎所有语言(包括c#)中,null的唯一默认合法操作是检查其他内容是否等于它(在.Net ==默认为引用相等)。

&lt; =和&gt; =没有意义(如果他们这样做会有非常奇怪的行为)

某些语言(SQL可能是最知名的)不允许使用“标准”等式运算符来使其更加清晰。在SQL null == null不是真的,并且兼容的服务器将拒绝您尝试通过文字执行此操作的查询。

C#采用与其遗产相同的路线(C风格命令式语言),其中对空值的测试基于测试其中的位为零(事情变得稍微复杂但从根本上说是正在发生的事情)。因此,只有引用类型才能真正为空(Nullable<T>在幕后有很多魔法使它看起来像它,但实际上它是不是空的)。这意味着引用相等语义很好地遵循null语义,因此允许== null。

其他语言以不同的方式实现null(例如SQL,其中任何东西都可以为null,因此某些东西的'nullness'必须存储在它之外(很像Nullable)。这意味着传统的平等使用不需要作为主要关注点,null可以是真正特殊的,而不是某些类型的特殊情况。 有关null特殊性的更多信息,请查看This question has a list of such languages

大多数引用类型都没有定义一个&gt; =或&lt; =运算符,所以在实践中几乎没有问题,= =和&lt; =之间的断开连接(通常如果某些事情对于==是真的,那么它将是真的&lt; =和&gt; =以及。)

答案 2 :(得分:4)

你可以试试这个:

int? n1 = null;
int? n2 = null;

// Test for equality
Assert.IsTrue((n1.HasValue && n2.HasValue && n1.Value == n2.Value) || (!n1.HasValue && !n2.HasValue));

// Test for less than or equal to
Assert.IsTrue(n1.HasValue && n2.HasValue && n1.Value <= n2.Value);

答案 3 :(得分:0)

Nullable类型被包装到System.Nullable对象中,所以你不比较int值,你比较引用。要比较这些值,你需要这样做:

Assert.IsTrue(n1.Value <= n2.Value);

我在blog上写了一篇关于可空的内容。

编辑: 但在你的情况下,n1和n2为空,所以你甚至无法比较这些值。