欢迎访问 生活随笔!

生活随笔

当前位置: 首页 >

java if hasvalue_首选:可为空 .HasValue或Nullable !=空吗?

发布时间:2024/8/23 59 豆豆
生活随笔 收集整理的这篇文章主要介绍了 java if hasvalue_首选:可为空 .HasValue或Nullable !=空吗? 小编觉得挺不错的,现在分享给大家,帮大家做个参考.

我一直使用Nullable<>.HasValue因为我喜欢这种语义。 但是,最近我正在开发其他人的现有代码库,其中他们专门使用Nullable<> != null 。

是否有理由优先使用一个,还是纯粹是偏爱?

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

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

#1楼

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

#2楼

我通过使用不同的方法将值分配给可为null的int进行了一些研究。 这是我做各种事情时发生的事情。 应该澄清发生了什么。 请记住: Nullable还是速记的something? 是一种结构,编译器似乎为此进行了大量工作,让我们将null当作类使用。

如下所示, SomeNullable == null和SomeNullable.HasValue将始终返回预期的true或false。 尽管下面没有演示, SomeNullable == 3也有效(假设SomeNullable是int? )。

虽然SomeNullable.Value会让我们运行时错误,如果我们分配null给SomeNullable 。 实际上,由于重载运算符,重载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);初始化int? val = new int?(null); int? val = new int?(null); ,如果将null传递给构造函数,则会产生COMPILE时间错误,因为可为空的对象的VALUE不可为空。 只有包装对象本身可以等于null。

同样,我们将从以下位置获得编译时错误:

int? val = new int?();

val.Value = null;

更不用说val.Value还是一个只读属性,这意味着我们甚至不能使用以下内容:

val.Value = 3;

但是同样,多态重载的隐式转换运算符使我们能够:

val = 3;

只要它能正常工作,就不用担心杂乱的东西。 :)

#3楼

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

#4楼

一般答案和经验法则:如果您有一个选择(例如,编写自定义序列化程序),可以在与object不同的管道中处理Nullable,并使用其特定的属性,则可以这样做并使用Nullable的特定属性。 因此,从一致的观点来看,应首选HasValue 。 一致的想法可以帮助您编写更好的代码,而不必花费太多时间在细节上。 例如,第二种方法会有效很多倍(主要是因为编译器内联和装箱,但是数字仍然非常有表现力):

public static bool CheckObjectImpl(object o)

{

return o != null;

}

public static bool CheckNullableImpl(T? o) where T: struct

{

return o.HasValue;

}

基准测试:

BenchmarkDotNet=v0.10.5, OS=Windows 10.0.14393

Processor=Intel Core i5-2500K CPU 3.30GHz (Sandy Bridge), ProcessorCount=4

Frequency=3233539 Hz, Resolution=309.2587 ns, Timer=TSC

[Host] : Clr 4.0.30319.42000, 64bit RyuJIT-v4.6.1648.0

Clr : Clr 4.0.30319.42000, 64bit RyuJIT-v4.6.1648.0

Core : .NET Core 4.6.25009.03, 64bit RyuJIT

Method | Job | Runtime | Mean | Error | StdDev | Min | Max | Median | Rank | Gen 0 | Allocated |

-------------- |----- |-------- |-----------:|----------:|----------:|-----------:|-----------:|-----------:|-----:|-------:|----------:|

CheckObject | Clr | Clr | 80.6416 ns | 1.1983 ns | 1.0622 ns | 79.5528 ns | 83.0417 ns | 80.1797 ns | 3 | 0.0060 | 24 B |

CheckNullable | Clr | Clr | 0.0029 ns | 0.0088 ns | 0.0082 ns | 0.0000 ns | 0.0315 ns | 0.0000 ns | 1 | - | 0 B |

CheckObject | Core | Core | 77.2614 ns | 0.5703 ns | 0.4763 ns | 76.4205 ns | 77.9400 ns | 77.3586 ns | 2 | 0.0060 | 24 B |

CheckNullable | Core | Core | 0.0007 ns | 0.0021 ns | 0.0016 ns | 0.0000 ns | 0.0054 ns | 0.0000 ns | 1 | - | 0 B |

基准代码:

public class BenchmarkNullableCheck

{

static int? x = (new Random()).Next();

public static bool CheckObjectImpl(object o)

{

return o != null;

}

public static bool CheckNullableImpl(T? o) where T: struct

{

return o.HasValue;

}

[Benchmark]

public bool CheckObject()

{

return CheckObjectImpl(x);

}

[Benchmark]

public bool CheckNullable()

{

return CheckNullableImpl(x);

}

}

PS 。 人们说建议“由于始终如一的想法而首选HasValue”是无关的和无用的。 您可以预测其性能吗?

public static bool CheckNullableGenericImpl(T? t) where T: struct

{

return t != null; // or t.HasValue?

}

PPS人们继续CheckNullableGenericImpl但没有人试图预测CheckNullableGenericImpl性能。 而且那里的编译器不会帮助您用HasValue替换!=null 。 如果您对性能感兴趣,则应直接使用HasValue 。

#5楼

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

这就是为什么:

假设我们有一些带有可为空的双变量SomeDouble Foo类

public class Foo

{

public double? SomeDouble;

//some other properties

}

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

public IEnumerable GetNonNullFoosWithSomeDoubleValues(IEnumerable 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

}

在这种情况下,我建议总是选择较短的

总结

以上是生活随笔为你收集整理的java if hasvalue_首选:可为空 .HasValue或Nullable !=空吗?的全部内容,希望文章能够帮你解决所遇到的问题。

如果觉得生活随笔网站内容还不错,欢迎将生活随笔推荐给好友。