Nullable.HasValue 或 Nullable之间有什么区别? != 空?

发布于 2024-07-15 11:15:42 字数 352 浏览 7 评论 0原文

我总是使用 Nullable<>.HasValue 因为我喜欢它的语义。 然而,最近我正在研究其他人的现有代码库,他们在其中使用了 Nullable<> 。 != null 专门代替。

是否有理由使用其中一种而不是另一种,或者纯粹是偏好?

  1. <前><代码>int? A; if (a.HasValue) // ...

  1. int?   乙; 
      if (b != null) 
          // ... 
      

I always used Nullable<>.HasValue because I liked the semantics. However, recently I was working on someone else's existing codebase where they used Nullable<> != null exclusively instead.

Is there a reason to use one over the other, or is it purely preference?

  1. int? a;
    if (a.HasValue)
        // ...
    

vs.

  1. int? b;
    if (b != null)
        // ...
    

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

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

发布评论

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

评论(5

花辞树 2024-07-22 11:15:42

编译器将 null 比较替换为对 HasValue 的调用,因此没有真正的区别。 只需选择对您和您的同事来说更具可读性/更有意义的方法即可。

The compiler replaces null comparisons with a call to HasValue, so there is no real difference. Just do whichever is more readable/makes more sense to you and your colleagues.

烟火散人牵绊 2024-07-22 11:15:42

我更喜欢 (a != null) ,以便语法与引用类型匹配。

I prefer (a != null) so that the syntax matches reference types.

向地狱狂奔 2024-07-22 11:15:42

我对此进行了一些研究,使用不同的方法将值分配给可为 null 的 int。 这是我做各种事情时发生的事情。 应该澄清是怎么回事。
请记住:Nullable 或简写 something? 是一个结构体,编译器似乎做了很多工作让我们使用 null 就好像这是一堂课。
正如您将在下面看到的,SomeNullable == nullSomeNullable.HasValue 将始终返回预期的 true 或 false。 尽管下面没有演示,SomeNullable == 3 也是有效的(假设 SomeNullable 是一个 int?)。
如果我们将 null 分配给 SomeNullableSomeNullable.Value 会导致运行时错误。 事实上,这是 nullables 可能给我们带来问题的唯一情况,这要归功于重载运算符、重载 object.Equals(obj) 方法以及编译器优化和猴子业务的组合。

以下是我运行的一些代码的描述,以及它在标签中产生的输出:

int? val = null;
lbl_Val.Text = val.ToString(); //Produced an empty string.
lbl_ValVal.Text = val.Value.ToString(); //Produced a runtime error. ("Nullable object must have a value.")
lbl_ValEqNull.Text = (val == null).ToString(); //Produced "True" (without the quotes)
lbl_ValNEqNull.Text = (val != null).ToString(); //Produced "False"
lbl_ValHasVal.Text = val.HasValue.ToString(); //Produced "False"
lbl_NValHasVal.Text = (!(val.HasValue)).ToString(); //Produced "True"
lbl_ValValEqNull.Text = (val.Value == null).ToString(); //Produced a runtime error. ("Nullable object must have a value.")
lbl_ValValNEqNull.Text = (val.Value != null).ToString(); //Produced a runtime error. ("Nullable object must have a value.")

好的​​,让我们尝试下一个初始化方法:

int? val = new int?();
lbl_Val.Text = val.ToString(); //Produced an empty string.
lbl_ValVal.Text = val.Value.ToString(); //Produced a runtime error. ("Nullable object must have a value.")
lbl_ValEqNull.Text = (val == null).ToString(); //Produced "True" (without the quotes)
lbl_ValNEqNull.Text = (val != null).ToString(); //Produced "False"
lbl_ValHasVal.Text = val.HasValue.ToString(); //Produced "False"
lbl_NValHasVal.Text = (!(val.HasValue)).ToString(); //Produced "True"
lbl_ValValEqNull.Text = (val.Value == null).ToString(); //Produced a runtime error. ("Nullable object must have a value.")
lbl_ValValNEqNull.Text = (val.Value != null).ToString(); //Produced a runtime error. ("Nullable object must have a value.")

与之前一样。 请记住使用 int 进行初始化? val = new int?(null);,如果将 null 传递给构造函数,则会产生编译时错误,因为可空对象的 VALUE 不可为空。 只有包装对象本身可以等于 null。

同样,我们会得到一个编译时错误:

int? val = new int?();
val.Value = null;

更不用说 val.Value 无论如何都是一个只读属性,这意味着我们甚至不能使用类似的东西:

val.Value = 3;

但同样,多态重载隐式转换运算符让我们可以做到:

val = 3;

无需担心多东西,只要它能正常工作即可? :)

I did some research on this by using different methods to assign values to a nullable int. Here is what happened when I did various things. Should clarify what's going on.
Keep in mind: Nullable<something> or the shorthand something? is a struct for which the compiler seems to be doing a lot of work to let us use with null as if it were a class.
As you'll see below, SomeNullable == null and SomeNullable.HasValue will always return an expected true or false. Although not demonstrated below, SomeNullable == 3 is valid too (assuming SomeNullable is an int?).
While SomeNullable.Value gets us a runtime error if we assigned null to SomeNullable. This is in fact the only case where nullables could cause us a problem, thanks to a combination of overloaded operators, overloaded object.Equals(obj) method, and compiler optimization and monkey business.

Here is a description of some code I ran, and what output it produced in labels:

int? val = null;
lbl_Val.Text = val.ToString(); //Produced an empty string.
lbl_ValVal.Text = val.Value.ToString(); //Produced a runtime error. ("Nullable object must have a value.")
lbl_ValEqNull.Text = (val == null).ToString(); //Produced "True" (without the quotes)
lbl_ValNEqNull.Text = (val != null).ToString(); //Produced "False"
lbl_ValHasVal.Text = val.HasValue.ToString(); //Produced "False"
lbl_NValHasVal.Text = (!(val.HasValue)).ToString(); //Produced "True"
lbl_ValValEqNull.Text = (val.Value == null).ToString(); //Produced a runtime error. ("Nullable object must have a value.")
lbl_ValValNEqNull.Text = (val.Value != null).ToString(); //Produced a runtime error. ("Nullable object must have a value.")

Ok, lets try the next initialization method:

int? val = new int?();
lbl_Val.Text = val.ToString(); //Produced an empty string.
lbl_ValVal.Text = val.Value.ToString(); //Produced a runtime error. ("Nullable object must have a value.")
lbl_ValEqNull.Text = (val == null).ToString(); //Produced "True" (without the quotes)
lbl_ValNEqNull.Text = (val != null).ToString(); //Produced "False"
lbl_ValHasVal.Text = val.HasValue.ToString(); //Produced "False"
lbl_NValHasVal.Text = (!(val.HasValue)).ToString(); //Produced "True"
lbl_ValValEqNull.Text = (val.Value == null).ToString(); //Produced a runtime error. ("Nullable object must have a value.")
lbl_ValValNEqNull.Text = (val.Value != null).ToString(); //Produced a runtime error. ("Nullable object must have a value.")

All the same as before. Keep in mind that initializing with int? val = new int?(null);, with null passed to the constructor, would have produced a COMPILE time error, since the nullable object's VALUE is NOT nullable. It is only the wrapper object itself that can equal null.

Likewise, we would get a compile time error from:

int? val = new int?();
val.Value = null;

not to mention that val.Value is a read-only property anyway, meaning we can't even use something like:

val.Value = 3;

but again, polymorphous overloaded implicit conversion operators let us do:

val = 3;

No need to worry about polysomthing whatchamacallits though, so long as it works right? :)

屌丝范 2024-07-22 11:15:42

在 VB.Net 中,当可以使用 .HasValue 时,请勿使用 IsNot Nothing。 我刚刚通过在一个地方用 .HasValue 替换 IsNot Nothing 解决了“操作可能会破坏运行时稳定性”中等信任错误。 我不太明白为什么,但编译器中发生了不同的事情。 我认为 C# 中的 != null 可能也有同样的问题。

In VB.Net, do NOT use IsNot Nothing when you can use .HasValue. I just solved an "Operation could destabilize the runtime" Medium trust error by replacing IsNot Nothing with .HasValue in one spot. I don't really understand why, but something is happening differently in the compiler. I would assume that != null in C# may have the same issue.

长亭外,古道边 2024-07-22 11:15:42

如果您使用 linq 并希望保持代码简短,我建议始终使用 !=null

这就是原因:

假设我们有一些类 Foo ,其带有 nullable double 变量 SomeDouble

public class Foo
{
    public double? SomeDouble;
    //some other properties
}   

如果在代码中的某个地方,我们希望从 Foo 集合中获取具有非 null SomeDouble 值的所有 Foo(假设集合中的某些 foo 也可以为 null) ,我们最终至少有三种方式来编写我们的函数(如果我们使用 C# 6):

public IEnumerable<Foo> GetNonNullFoosWithSomeDoubleValues(IEnumerable<Foo> foos)
{
     return foos.Where(foo => foo?.SomeDouble != null);
     return foos.Where(foo=>foo?.SomeDouble.HasValue); // compile time error
     return foos.Where(foo=>foo?.SomeDouble.HasValue == true); 
     return foos.Where(foo=>foo != null && foo.SomeDouble.HasValue); //if we don't use C#6
}

在这种情况下,我建议始终选择较短的一种

If you use linq and want to keep your code short, I recommand to always use !=null

And this is why:

Let imagine we have some class Foo with a nullable double variable SomeDouble

public class Foo
{
    public double? SomeDouble;
    //some other properties
}   

If somewhere in our code we want to get all Foo with a non null SomeDouble values from a collection of Foo (assuming some foos in the collection can be null too), we end up with at least three way to write our function (if we use C# 6) :

public IEnumerable<Foo> GetNonNullFoosWithSomeDoubleValues(IEnumerable<Foo> foos)
{
     return foos.Where(foo => foo?.SomeDouble != null);
     return foos.Where(foo=>foo?.SomeDouble.HasValue); // compile time error
     return foos.Where(foo=>foo?.SomeDouble.HasValue == true); 
     return foos.Where(foo=>foo != null && foo.SomeDouble.HasValue); //if we don't use C#6
}

And in this kind of situation I recommand to always go for the shorter one

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