簡體   English   中英

在c#中訪問可空值的最佳方法

[英]Best way to access nullable values in c#

在我們的C#代碼中,我們已經在嘗試訪問變量之前測試了變量是否為null。

if (myInt.HasValue) {
  var yourInt = myInt;

  // do something with yourInt
}

我的問題:使用可空屬性是否有區別,就好像它在測試之后不是以下情況一樣?

if (myInt.HasValue) {
  var yourInt = myInt.Value; // see the difference?

  // do something with yourInt
}

這只是一個偏好問題,或者即使在可以為空的對象通過該測試之后,使用.Value還是有明顯的原因或性能影響嗎?

UPDATE

我擴展了我的第二個例子,我們已經使用HasValue測試,但我們使用.Value來訪問該值。

更新2

我更新了示例以使用var s,因為在我們的代碼中我們實際上並沒有使用int類型,抱歉這個糟糕的例子。 在我們的代碼中,我們實際上只是使用NHibernate Criteria查詢中的對象 - Expression.Eq("thing", myInt)查詢。

這不會引發編譯錯誤。 我試圖簡化示例以獲得我的問題的根源而不涉及NHibernate。 很抱歉,如果這會使某些答案無效。 如果我們強制使用另一種方法來查找值而不是顯式調用.Value我只是想看看性能是否受到打擊。

更新:這個問題是我2012年12月20日的博客主題 我將在2013年12月和1月初的更多關於此優化的想法中跟進。感謝您提出的好問題!


如果我們強制使用另一種方法來查找值而不是顯式調用.Value,我只是想看看性能是否受到打擊

首先,如果您有性能問題,那么您是唯一可以回答問題的人 ,並且您可以通過秒表嘗試兩種方式並查看哪一個更快 來回答問題 對我來說,為什么人們經常在StackOverflow上問這個問題,這是一個謎。 這就像說“嘿,互聯網,這里有兩匹馬的照片。哪一個跑得更快?” 我們怎么知道? 比賽他們,然后你會知道。 他們是你的馬。

其次,你在一般意義上提出錯誤的問題。 問題不應該是“是否會對性能產生影響?”而是“對性能造成不可接受的打擊?” 而且,我們不知道您接受或不接受的是什么。

第三,你是在非常具體的意義上提出錯誤的問題。 這里要問的正確問題是,如果您對納米級優化感興趣,使用Value getter或GetValueOrDefault方法哪個更快?

答案是通常GetValueOrDefault方法比Value快。 為什么? 因為區別在於:

if (this.HasValue) return this.value; else throw new Exception();

return this.value; 

那有什么區別? 抖動可能不會內聯前一種方法 ,因此您需要支付高達幾納秒的罰款才能實現額外的呼叫間接。

如果幾納秒的罰款與你相關,那么(1)祝賀編寫一個只運行幾微秒的程序,(2)你需要非常仔細地測量,看看是否有任何真正的差異,因為納秒非常小。

這只是一個偏好問題還是有一個明顯的原因

int yourInt = myInt.Value;

如果HasValuefalse則拋出

因此,如果您不想體驗InvalidOperationException ,請首先檢查HasValue

注意

int yourInt = myInt;

是不合法的(編譯時失敗)因為int?沒有隱式轉換int? to int (如果值為null ,那么將int?為沒有合理的值)。 你可以說:

int yourInt = (int)myInt;

請注意,如果myIntnull ,則會拋出此null ,就像訪問Value

最后一點,如果您接受默認值,則可以使用null合並運算符並說:

int yourInt = myInt ?? defaultValue;

這相當於:

int yourInt;
if(myInt.HasValue) {
    yourInt = myInt.Value;
}
else {
    yourInt = defaultValue;
}

這不會引發編譯錯誤。 我試圖簡化示例以獲得我的問題的根源而不涉及NHibernate。 很抱歉,如果這會使某些答案無效。 如果我們強制使用另一種方法來查找值而不是顯式調用.Value,我只是想看看性能是否受到打擊。

沒有。性能在這里完全無關緊要,特別是如果涉及數據庫的話。 這絕對沒有任何有意義的性能差異,並且肯定不會成為瓶頸。 只需編寫最清晰的代碼即可。 坦率地說,我發現.Value是最清楚的。

此代碼無效:

if (myInt.HasValue) {
  int yourInt = myInt;

  // do something with yourInt
}

如果您不想使用Value屬性,則必須使用顯式強制轉換,或使用null合並運算符或GetValueOrDefault ,例如

int yourInt = (int) myInt;

無論如何,演員最終被編譯為對Value屬性的訪問,IIRC。

所以,是的,即使你已經測試過一個值是非空的,你仍然需要做一些事情來將它轉換為底層值 - 只是為了讓它進行編譯。 編譯器不會嘗試分析“可能的無效”(例如,如果它是一個實例變量,例如,由於訪問之間的線程可能會改變)。 它只遵循允許對可以為空的表達式執行的操作的規則,並且隱式轉換為非可空類型不是您允許執行的操作之一...

有一個原因你不能直接調用.Value :當myInt為null時,你會期望yourInt的值是多少?

如果要使其具有默認值(例如:0),則可以在可空的int上創建擴展方法,如.ValueOrDefault()

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM