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 !=空吗?的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: java xmpp openfire_X
- 下一篇: nodejs 防宕机_pm2实战,让你的