วิธีที่ดีที่สุดในการตรวจสอบบูล nullable ในนิพจน์เงื่อนไข (ถ้า…)


207

ฉันสงสัยว่าอะไรคือไวยากรณ์ที่สะอาดและเข้าใจได้ดีที่สุดสำหรับการตรวจสอบเงื่อนไขในบูลที่ไม่มีค่า

รูปแบบการเข้ารหัสดีหรือไม่ดีต่อไปนี้หรือไม่ มีวิธีในการแสดงสภาพที่ดีขึ้น / สะอาดขึ้นหรือไม่?

bool? nullableBool = true;
if (nullableBool ?? false) { ... }
else { ... }

โดยเฉพาะอย่างยิ่งถ้า (nullableBool ?? เท็จ)ส่วนหนึ่ง ฉันไม่ชอบif (x.HasValue && x.Value)สไตล์ ...

(ไม่แน่ใจว่าคำถามถูกถามมาก่อนหรือไม่พบสิ่งที่คล้ายกับการค้นหา)

คำตอบ:


361

ฉันคิดว่าผู้คนมากมายให้ความสนใจกับความจริงที่ว่าค่านี้เป็นโมฆะและไม่ได้คิดเกี่ยวกับสิ่งที่พวกเขาต้องการจริงๆ :)

bool? nullableBool = true;
if (nullableBool == true) { ... } // true
else { ... } // false or null

หรือถ้าคุณต้องการตัวเลือกเพิ่มเติม ...

bool? nullableBool = true;
if (nullableBool == true) { ... } // true
else if (nullableBool == false) { ... } // false
else { ... } // null

(nullableBool == true)จะไม่กลับมาจริงถ้าบูล? เป็นโมฆะ: P


2
ฉันไม่ได้ตระหนักว่าการเปรียบเทียบที่ไม่มีค่ามีความหมายเช่นนี้ รายละเอียดสามารถดูได้ที่msdn.microsoft.com/en-us/library/2cf62fcy.aspx
Micah Zoltu

79

วิธีการใช้GetValueOrDefaultซึ่งค่อนข้างอธิบายตนเองและอนุญาตให้ใช้ค่าเริ่มต้นที่คุณต้องการ:

if (nullableBool.GetValueOrDefault(false)) {
}

6
ขึ้นอยู่กับบริบทของวิธีการนี้ที่อาจเกิดขึ้นSystem.NotSupportedException: LINQ to Entities does not recognize the method 'Boolean GetValueOrDefault()' method, and this method cannot be translated into a store expression.
Nano Taboada

3
ฉันชอบวิธีการนี้เพราะมันทำงานในคำสั่งที่ไม่ใช่ if (เช่นการมอบหมาย)
paultechguy

48

คุณอาจไม่ชอบ แต่ฉันพบว่าเป็นการส่วนตัว

if (x.HasValue && x.Value)

อ่านได้มากที่สุด ทำให้ชัดเจนว่าคุณกำลังทำงานกับประเภท nullable และทำให้ชัดเจนว่าคุณกำลังตรวจสอบก่อนว่าประเภท nullable มีค่าก่อนที่จะดำเนินการตามเงื่อนไข

หากคุณใช้เวอร์ชันของคุณและแทนที่ตัวแปรด้วย x จะเป็นการอ่าน:

if (x ?? false)

ชัดเจนหรือไม่ ชัดเจนหรือไม่ว่า x เป็นชนิด nullable? ฉันจะให้คุณตัดสินใจ


AFAIK, ?? ใช้งานได้กับประเภทที่ไม่มีค่าเท่านั้น รวมทั้งตัวแปรควรมีชื่อดีกว่า x :)
FireSnake

5
โดย "ประเภท nullable" ฉันหมายถึงเฉพาะ System.Nullable ประเภท ประเภทการอ้างอิงใด ๆ อาจเป็นโมฆะ นอกจากนี้หากคุณจำเป็นต้องใช้ชนิดของตัวแปรเป็นส่วนหนึ่งของชื่อแล้วนั่นคือสิ่งที่บ่งบอกว่ารหัสของคุณไม่ชัดเจน
Dan Diplo

@DanDiplo วิธีเขียน UT สำหรับสิ่งนี้
Prashant Yadav

xดีในบริบทและบางครั้งก็สะอาด เพื่อปัญญา:var openOrders = orders.Where(x=>x.Open ?? false)
nothingisnecessary

21

หากคุณต้องการที่จะถือว่าnullเป็นเท็จแล้วฉันจะบอกว่าวิธีที่สั้นที่สุดที่จะทำคือการใช้ตัวดำเนินการรวมกันโมฆะ ( ??) ตามที่คุณอธิบาย:

if (nullableBool ?? false) { ... }

8

แค่คิดบูล? มีค่า 3 ค่าสิ่งต่าง ๆ ก็จะง่ายขึ้น:

if (someNullableBool == true)     // only if true
if (someNullableBool == false)    // only if false
if (someNullableBool == null)     // only if null

8

ใช้ส่วนขยาย

public static class NullableMixin {
    public static bool IsTrue(this System.Nullable<bool> val) {
        return val == true;
    }
    public static bool IsFalse(this System.Nullable<bool> val) {
        return val == false;
    }
    public static bool IsNull(this System.Nullable<bool> val) {
        return val == null;
    }
    public static bool IsNotNull(this System.Nullable<bool> val) {
        return val.HasValue;
    }
}


Nullable<bool> value = null;
if(value.IsTrue()) {
// do something with it
}

ถ้าคุณต้องการที่จะต้องพิจารณาnullเป็นtrue?
Thibault Falise

IsTrue () | IsNull () .. :) ฉันทำซ้ำตรรกะวิธี SQL ทำงานร่วมกับ nulls ฉันคิดว่ามันเป็นไวยากรณ์ที่สะอาดและเข้าใจได้มากที่สุด
Andrey Frolov

มันควรจะเป็นสาธารณะคงที่บูล IsFalse (System.Nullable val) นี้ {return! val ?? จริง; } พิจารณาว่า null เป็นเท็จ
Michael Freidgeim

2
มันอาจจะหายไปอัฒภาค (;) ในสองวิธีสุดท้าย (เช่น IsNull และ IsNotNull)
เกล็นการ์สัน

4

ให้ตรวจสอบวิธีการเปรียบเทียบกับ null ถูกกำหนด:

static void Main()
    {
        Console.WriteLine($"null != null  => {null != null}");
        Console.WriteLine($"null == null  => {null == null}");
        Console.WriteLine($"null != true  => {null != true}");
        Console.WriteLine($"null == true  => {null == true}");
        Console.WriteLine($"null != false => {null != false}");
        Console.WriteLine($"null == false => {null == false}");
    }

และผลลัพธ์คือ:

null != null  => False                                                                                                                                                                                                                                  
null == null  => True                                                                                                                                                                                                                                   
null != true  => True                                                                                                                                                                                                                                   
null == true  => False                                                                                                                                                                                                                                  
null != false => True                                                                                                                                                                                                                                   
null == false => False

ดังนั้นคุณสามารถใช้อย่างปลอดภัย:

// check if null or false
if (nullable != true) ...

// check if null or true
if (nullable != false) ...

// check if true or false
if (nullable != null) ...

ฉันแค่สงสัยว่าทำไมเราทำไม่ได้ถ้า (เป็นโมฆะ) .... ที่จะจัดการ แต่ต้องได้รับการปฏิบัติด้วยความระมัดระวังif(nullable)...else if(!nulllable)...else..
IronHide

ฉันจะบอกว่าในช่วงหลายปีที่ผ่านมารูปแบบการเข้ารหัส (เนื่องจากความพร้อมใช้งานของเครื่องมือเช่น stylecop, เครื่องวิเคราะห์ ฯลฯ ) มีความต้องการโค้ดที่ชัดเจนโปร่งใส "เจตนายืนยัน" มากขึ้นเรื่อย ๆ (เช่นแนะนำให้ใช้วงเล็บที่ไม่จำเป็นเพียงเพื่อยืนยันการใช้งาน ลำดับความสำคัญของผู้ให้บริการหรือใช้ระบบคำอธิบายประกอบ / สัญญาต่างๆ) IMO ที่แนะนำไวยากรณ์ดังกล่าวจะทำให้เกิดความสับสนมากขึ้นเนื่องจากระดับของความไม่ชัดเจนว่าการจัดการ nullables มีประโยชน์มากกว่าประโยชน์อย่างไร
Sz. Moncz

4

ที่จริงฉันคิดว่านั่น(nullableBool ?? false)เป็นตัวเลือกที่ถูกต้องตามกฎหมายโดยเฉพาะอย่างยิ่งเมื่อคุณพยายามประเมินบูลแบบ nullable ใน linq

ตัวอย่างเช่น:
array.Select(v => v.nullableBool ?? false)
(from v in array where v.nullableBool ?? false)

ฉันคิดว่าสะอาดกว่าหรือไม่เมื่อเทียบกับ:
array.Select(v => v.nullableBool.HasValue ? v.nullableBool.Value : false)
(from v in array where v.nullableBool.HasValue ? v.nullableBool.Value : false)


1

หากคุณเพียงต้องการทดสอบtrueกับnull/ falseหนึ่งที่ฉันเพิ่งใช้และอ่านค่อนข้างดีคือ

bool? someCondition = null
if (someCondition.Equals(true))
...

1
คุณไม่ได้รับข้อยกเว้นอ้างอิงว่างเปล่าที่นี่หรือไม่
Chase Florell

@ChaseFlorell ฉันต้องตรวจสอบสิ่งนี้อีกครั้งในหน้าต่าง VS Interactive .. สิ่งที่ต้องจำก็คือชนิดของ somecondition นั้นเป็น Nullable <bool> คุณยังสามารถเรียกวิธีการที่สืบทอดมาจาก object (เช่น Equals), HasValue และ GetValueOrDefault แต่ไม่ใช่ค่า
ds4940

น่าสนใจฉันเห็นตอนนี้แล้ว ยังคงร่างสำหรับประเภทการอ้างอิงdotnetfiddle.net/8cAI21
Chase Florell

0

ฉันคิดว่ามันขึ้นอยู่กับคุณ ฉันคิดอย่างแน่นอนว่าวิธีการ .HasValue นั้นสามารถอ่านได้มากขึ้นโดยเฉพาะกับนักพัฒนาที่ไม่คุ้นเคยกับ ?? วากยสัมพันธ์

อีกจุดหนึ่งของบูลีนแบบ nullable คือมันเป็น tristate ดังนั้นคุณอาจต้องการทำอย่างอื่นเมื่อมันเป็นโมฆะและไม่ใช่ค่าเริ่มต้นที่เป็นเท็จ


0

กำหนด enum

public enum PublishMode { Edit, View }

คุณสามารถทำมันได้ที่นี่

 void MyMethod(PublishMode? mode)
    {
       var publishMode = mode ?? PublishMode.Edit;

//or
       if (mode?? PublishMode.Edit == someValue)
       ....
    }

nullable booleanไม่ได้ตอบคำถามซึ่งเป็นพิเศษเกี่ยวกับ
ToolmakerSteve

0

หากคุณอยู่ในสถานการณ์ที่คุณไม่สามารถควบคุมได้ว่าส่วนใดส่วนหนึ่งของเงื่อนไขกำลังตรวจสอบค่าที่เป็นโมฆะคุณสามารถลองทำสิ่งต่อไปนี้ได้เสมอ:

if( someInt == 6 && someNullableBool == null ? false : (bool)someNullableBool){
    //perform your actions if true
}

ฉันรู้ว่ามันไม่ใช่วิธีการที่พิถีพิถันที่ใส่ไตรภาคในคำสั่ง if แต่จะแก้ไขปัญหาได้อย่างหมดจด

แน่นอนว่านี่เป็นวิธีพูดด้วยตนเอง GetValueOrDefault(false)


3
วิธีแก้ปัญหาที่ให้ไว้ใน OP นั้นเหมือนกัน แต่มีโค้ดที่น้อยกว่ามาก นี่ไม่ใช่ข้อได้เปรียบเลย
Servy
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.