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

发布于 2024-07-17 05:32:04 字数 144 浏览 3 评论 0原文

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

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

你知道为什么吗?

Surprisingly the code bellow will not succeed.

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

Do you know why?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

ζ澈沫 2024-07-24 05:32:04

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

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

如果您确实希望将 null 视为一个值,那么您可以使用 GetValueOrDefaultMethod() 将 null 与默认值等同。 例如,

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

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

Using boolean logic with null nullable values in C# (and VB.Net) often times defies logic. I find the best way to make sense of it is to remember that "null is not a value". Because null is not a value you cannot do any operations on it. Hence things like "1 > null" and "1 < null" are both true.

Here is a detailed guide: http://msdn.microsoft.com/en-us/library/2cf62fcy.aspx

If you do want to treat null as a value then you could use the GetValueOrDefaultMethod() to equate null with the default value. For example

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

This is a bit verbose but it will get the job done.

长发绾君心 2024-07-24 05:32:04

这要么是一个拼写错误,您的意思是“==”而不是“<=”,要么您误解了空值的工作原理。

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

<= 和 >= 没有意义(因为如果它们这样做的话,它们会有非常奇怪的行为)

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

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

其他语言以不同的方式实现 null(例如 SQL,其中任何内容都可以为 null,因此某些内容的“nullness”必须存储在其外部(非常类似于 Nullable)。这意味着等式的常规使用不必是主要的关注和空可以是真正的特殊而不是某些类型的特殊情况。
有关 null 特殊性的更多信息,请查看 这个问题有一个此类语言的列表

大多数引用类型没有定义 >= 或 <= 运算符,因此在实践中 == 之间的断开几乎没有问题和 <= (通常,如果 == 为真,则 <= 和 >= 也为真)。

Either this is a typo and you meant "==" not "<=" or you misunderstand how nulls work.

In almost all languages (including c#) the only default legal operation on null is to check if something else is equal to it (in .Net == is by default reference equality).

<= and >= are not meaningful (as they would have very strange behaviour if they did)

Some languages (SQL being possibly the most well known) disallow the use of 'standard' equality operators to make this even more clear. in SQL null == null is NOT true, and a compliant server will refuse queries where you attempt to do this via a literal.

C# takes the same route as it's heritage (C style imperative languages) where the test for a null value is based on testing that the bits in it are zero (things get somewhat more complex but fundamentally that's what is happening). As such only reference types can truly be null (Nullable<T> has a lot of magic behind the scenes to make it look like it is but actually under the hood it isn't null). This means that the reference equality semantics follow nicely into null semantics, thus the == null is allowed.

Other languages implement null in a different fashion (for example SQL where anything can be made null thus the 'nullness' of something must be stored outside of it (much like Nullable). This means that the conventional use of equality need not be the primary concern and null can be truly special rather than a special case of certain types.
For further information on the specialness of null take a look at This question has a list of such languages

Most reference types do not define a >= or <= operator so there is little problem in practice with the disconnect between == and <= (where normally if something is true for == it would be true for <= and >= as well).

感情洁癖 2024-07-24 05:32:04

你可以试试这个:

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);

You can try this:

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);
无所的.畏惧 2024-07-24 05:32:04

可空类型被包装到 System.Nullable 对象中,因此您不比较 int 值,而是比较引用。 要比较这些值,您需要这样做:

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

我在 上写了一些关于 nullable 的内容博客

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

Nullable types are wrapped into a System.Nullable object, so you don't compare the int value, you compare the reference. To compare the values, you need to make it like that:

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

I wrote a bit about nullable on my blog.

Edit:
But in your case n1 and n2 is null, so you can't even compare the values.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文