簡體   English   中英

Nullable有什么用? <bool> 類型?

[英]What is the use of Nullable<bool> type?

布爾變量可以保持真或假,而布爾? 也可以為空。

為什么我們需要bool的第三個值? 如果它不是真的 ,它是什么,它是== false

你能建議一個我喜歡布爾的場景嗎? 代替。

謝謝

出於多種原因,某些事情可能是真實的,錯誤的或未定義的。 如何回答“你的第三個孩子是女孩嗎?” 如果一個人只有兩個孩子? 真假都是不正確的。 Null適合說比較不適用。

各種答案一般討論可空類型的重要性。 可以為null的布爾值提供額外的答案。 在C#中很難理解,但如果你在任何數據庫中查看空值邏輯,那么很容易理解。

假設您正在跟蹤Shipments清單或表格。 Shipment有一個DeliveryDate ,但當然,您不知道這些信息,直到發貨很久,並且可能至少在貨物實際交付后幾天,當UPS最終通知您時。 當然, DeliveryDateNullable<DateTime> (或DateTime? )。

您想要檢索上周交付的所有貨件的清單。 所以你寫這個:

var deliveredThisWeek = shipments.Where(s => 
    s.DeliveryDate >= DateTime.Today.AddDays(-7));

是否應包含交貨日期為null貨件? (答案當然是否定的 。)

好的,那么這個怎么樣:

var deliveredBeforeThisWeek = shipments.Where(s =>
    s.DeliveryDate < DateTime.Today.AddDays(-7));

這些結果中是否應包含交貨日期為null貨件? 答案仍然否定的

所以現在你有一個奇怪的情況。 您可能會認為在這兩個查詢之間,您將收到系統中的所有貨件。 A | !A A | !A總是true ,對吧? 不是在你處理空值時。

即便是這個也無法得到你所有的結果:

var deliveredAnytime = shipments.Where(s =>
    (s.DeliveryDate >= DateTime.Today.AddDays(-7)) ||
    (s.DeliveryDate < DateTime.Today.AddDays(-7)));

那怎么可能呢?

為了准確地表示此邏輯,您需要一個不是真假的條件。 而且,C#在這里是一個不好的例子,因為它沒有像你真正期望的那樣實現邏輯。 但在SQLese中,它是有道理的,因為:

[DeliveryDate >= BeginningOfWeek] = NULL
[DeliveryDate <  BeginningOfWeek] = NULL

顯然, NULL OR NULL仍然是NULL ,而不是TRUE 這就是為什么你可以正確地說貨物在本周開始之前沒有交付, 並且之后沒有交付。 或者,更准確地說,我們不知道它何時交付,因此我們無法安全地說它確實符合這些條件。

但C#並不是那么一致。 在C#中,如果DeliveryDate為null,則:

(s.DeliveryDate >= beginningOfWeek) == false
(s.DeliveryDate < endOfWeek) == false

這為我們上面的查詢提供了正確的答案,所以你可能會想要說常規布爾邏輯足夠好,除了這個混亂之外:

var deliveredThisWeek = shipments.Where(s =>
    !(s.DeliveryDate < DateTime.Today.AddDays(-7));

啊啊...現在它給我們回送null交貨日期! 這不對! 在有人說“@Aaronaught,你在談論什么,當然是對的!那些貨物在上周之前沒有交付,所以情況應該覆蓋他們!” ,停下來思考一下。

NULL實際上並不意味着它們沒有被傳遞。 NULL表示我們不知道它們何時被傳遞。 職員可能會在明天拿到確認函,並在兩周前填寫DeliveryDate ,使我們剛收到的數據無效。 應該從該查詢返回空實例,但有。 如果在SQL中編寫相同的查詢,則會排除這些結果。

所以,當C#顯然沒有時,你為什么要關心Nullable<bool> 因此,您可以避免在自己的代碼中陷入此陷阱:

public static bool? IsThisWeek(DateTime? dt)
{
    return (dt != null) ? (bool?)(dt.Value > DateTime.Today.AddDays(-7)) : null;
}

var deliveredBeforeThisWeek = shipments.Where(s =>
    (!IsThisWeek(s.DeliveryDate) == true));

// Or, the equivalent:
var alsoDeliveredBeforeThisWeek = shipments.Where(s =>
    (IsThisWeek(s.DeliveryDate) == false));

這有點尷尬,但是正確的。 我們編寫了一個或多或少正確地傳達其意圖的查詢,並且(bool?)null不等於true false ,因此我們在兩種情況下都得到了正確的結果。

如果您需要評估答案可能是“我不知道”的情況 - 請使用bool? (AKA Nullable<bool>作為結果

這樣,調用者可以決定如何處理“我不知道”的響應,而不是簡單地選擇默認值。 別的什么意味着你的班級撒謊

null值表示“無值”或“未知值”。 在這種情況下,它不是真的,也不是假的,而是未定義的

請參閱: http//en.wikipedia.org/wiki/Many-valued_logic

當某些事情尚未得到回答時,這是好事 - 想想問卷調查。 你有一個y / n問題列表,只有一些已被回答。 您不希望將true或false發布到數據庫表,因為用戶尚未回答該問題。

除了true或false之外,它可能是未知的。在數據庫中,NULL通常表示未知或沒有值

懶惰的編程!

public bool MyProp
{
    get { return (myProp = myProp ?? GetPropValue()).Value; }
}
private bool? myProp;

空值意味着

  • 我不知道。
  • 目前數據不足
  • 盒子打開前貓的狀態
  • 我還沒有下定決心
  • 利潤

空值表示Mu

我在過濾值中使用它。 基本上我在數據庫中有一個bool字段,但我想要三種狀態:只返回值為true的行,只返回值為false的行,不過濾並返回所有行。

如果沒有可空的bool,我將不得不使用枚舉或第二個bool來確定“按此字段過濾是/否”這將增加膨脹。

可以為空可以表示如果你的程序可能需要知道的話,bool沒有被設置或初始化

好吧,我可以看到它被用作“尚未確定”的東西,我一直使用bool,有時只有兩個值不夠!! 例如:

bool? bl;

bl = true; //Yes

bl = false; //No

bl = null; // Not determined, so do nothing

在我看來,它只是bool的第三個價值。

如果您要使用Nullable bool,我會考慮使用Enum或其他數據結構。 當NULL的含義未知時,它可以幫助您避免錯誤。

最近,我錯誤地處理了Nullable bool。 我不會詳細介紹這個錯誤,但我只想說它要求完全回滾已經夠糟糕了。 我開始想知道在大多數應用程序中使用它是多么實用。 (在某種程度上,由於愚蠢的錯誤,我試圖堅持自己的驕傲🙂)

然后,我遇到了這個帖子和李的接受答案。

這似乎有道理,但是我用它花費的時間越多,答案在實踐中變為FALSE而不是NULL。 NULL太模糊了。

在回答這個問題之前,必須為NULL分配一個非常具體的含義。 NULL是否表示計算中存在錯誤? 如果在確定只有兩個孩子之前計算中有錯誤怎么辦? (我還會爭辯說,如果確實只有兩個孩子,可以在問題提交給該計划之前處理。)

因為我們不知道NULL意味着什么,因為它絕對不是真的(因為,它怎么可能?),最好的答案是假的。

此外,如果此問題確實返回NULL,我們已經向域引入了新定義。 這個定義的范圍是什么?

因此,看起來TRUE或FALSE狀態表示結果的確定性。 可以在至少三種不同狀態中設想NULL。 例如,“托馬斯昨晚去了酒吧”。

是的 - 是的,托馬斯去了酒吧。 (如果你認識托馬斯,最有可能的答案)假 - 不,托馬斯沒有去酒吧。 空 - 嗯? 可知 - 第一次計算出錯了。 例如,你問托馬斯這個問題,但他回答時打了個噴嚏,讓你暫時失聰。 再問他一次就能得到答案。

不可知 - 酒吧被燒毀,托馬斯跳過城鎮。 沒有現實的方法來得到答案。 (請不要在這里戳洞,但我知道你會這樣做)

不適用 - 請參閱上面關於三個孩子的例子,而不是欄和托馬斯。

NULL在這里意味着什么? 必須根據具體情況確定NULL的含義。 這就是為什么我認為使用Enum或其他結構通常更好,因為它更優雅地暴露了非二進制返回值背后的意圖。

您希望使用它來涵蓋“如果用戶既沒有指定既不是真也不指定該怎么辦?”的情況。

這只是一種涵蓋所有可能結果的方法。

假設已下訂單但尚未發貨。 Order.ShippedDate的價值是Order.ShippedDate

處理這種問題的老式方法是使用像DateTime.MinValue這樣的神奇值。 還有其他方法可以解決此問題(例如,包裝類型或附加的bool標志,表明訂單尚未發貨)。 這些都不是很令人滿意。 所需要的是一種統一的方法來處理丟失或未知值的問題。

因此,現代方法是允許Order.ShippedDate采用語義捕獲訂單尚未發貨的值。 這是可空類型扮演的角色。 從語義上講,你應該想到一個Nullable<T>的實例,其中HasValuefalse ,表示“缺失”或“未知”。

此外,數據庫長期允許列允許null 例如,您可以使用允許null的整數值列。 如果你不允許可以為空的int你如何從代碼中與這樣的列交互? 同樣,您可以使用上面提到的方法,但是當語言具有用於語義捕獲我們正在嘗試建模的情況的內置工具時,它會更好。

這是另一個用例。 考慮具有布爾屬性的分層數據結構。 在父項上設置此類屬性將應用於其所有子項,除非明確設置它們。 考慮Windows中的文件和文件夾的只讀權限(具有三態復選框)。

Parent1(readonly: true, evaluates true)
  |-Parent2(readonly: null, evaluates true)
    |-Child1(readonly: false, evaluates false)
    |-Child2(readonly: null, evaluates true)
 |-Parent3(readonly: false, evaluates false)
    |-Child1(readonly: false, evaluates false)
    |-Child2(readonly: null, evaluates false)

我認為在C#2中添加可空類型的主要動機(至少它是這樣的:-))是數據庫。 在數據庫中,任何數據類型都可以具有NULL值,並且在將這些數據映射到C#時,這是一個問題。 Nullable類型允許您非常優雅地處理這個問題 - 您可以使用int? bool? 和別的。 它們用於LINQ to SQL中。

第三個值對布爾值意味着什么,當然這取決於應用程序。 我想通常,這意味着值/字段不可用。

暫無
暫無

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

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