Cara terbaik untuk memeriksa bool yang dapat dibatalkan dalam ekspresi kondisi (jika ...)

208

Saya bertanya-tanya apa sintaks yang paling bersih dan dapat dimengerti untuk melakukan pemeriksaan kondisi pada bools nullable.

Apakah gaya pengkodean baik atau buruk berikut? Apakah ada cara untuk mengekspresikan kondisi lebih baik / lebih bersih?

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

terutama bagian if (nullableBool ?? false) . Saya tidak suka if (x.HasValue && x.Value)gaya ...

(tidak yakin apakah pertanyaan telah diajukan sebelumnya ... tidak dapat menemukan sesuatu yang mirip dengan pencarian)

FireSnake
sumber

Jawaban:

362

Saya pikir banyak orang berkonsentrasi pada fakta bahwa nilai ini dapat dibatalkan, dan tidak memikirkan apa yang sebenarnya mereka inginkan :)

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

Atau jika Anda ingin lebih banyak opsi ...

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

(nullableBool == true)tidak akan pernah mengembalikan true jika bool? adalah null: P

Artiom Chilaru
sumber
2
Saya tidak menyadari bahwa perbandingan nol dapat berarti seperti ini. Detail dapat ditemukan di msdn.microsoft.com/en-us/library/2cf62fcy.aspx
Micah Zoltu
79

Bagaimana dengan menggunakan GetValueOrDefault , yang cukup menjelaskan sendiri dan memungkinkan untuk menggunakan default apa pun yang Anda inginkan:

if (nullableBool.GetValueOrDefault(false)) {
}
Lucero
sumber
6
Tergantung konteksnya, pendekatan ini mungkin melemparSystem.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
Saya suka pendekatan ini karena ia juga bekerja dalam pernyataan non-jika (yaitu penugasan).
paultechguy
48

Anda mungkin tidak menyukainya, tetapi secara pribadi saya temukan

if (x.HasValue && x.Value)

yang paling mudah dibaca. Itu membuat jelas Anda bekerja dengan tipe nullable dan membuatnya jelas Anda pertama kali memeriksa apakah tipe nullable memiliki nilai sebelum bertindak berdasarkan kondisional.

Jika Anda mengambil versi Anda dan mengganti variabel dengan x juga berbunyi:

if (x ?? false)

Apakah itu jelas? Apakah jelas x adalah tipe yang dapat dibatalkan? Saya akan membiarkan Anda memutuskan.

Dan Diplo
sumber
afaik, ?? hanya bekerja pada tipe yang dapat dibatalkan. Plus variabel harus memiliki nama yang lebih bagus daripada x :)
FireSnake
5
Dengan "tipe nullable" yang saya maksud khusus tipe System.Nullable. Jenis referensi apa pun bisa nol. Juga, jika Anda perlu menggunakan jenis variabel sebagai bagian dari namanya maka itu menunjukkan kode Anda tidak jelas.
Dan Diplo
@DanDiplo Bagaimana cara menulis UT untuk ini?
Prashant Yadav
xbaik dalam konteks dan terkadang lebih bersih; yakni:var openOrders = orders.Where(x=>x.Open ?? false)
nothingisnecessary
21

Jika Anda ingin memperlakukan nullsebagai salah, maka saya akan mengatakan bahwa cara paling ringkas untuk melakukannya adalah dengan menggunakan operator null coalesce ( ??), seperti yang Anda jelaskan:

if (nullableBool ?? false) { ... }
Oded
sumber
8

Pikirkan bool saja? memiliki 3 nilai, maka segalanya menjadi lebih mudah:

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

sumber
8

Gunakan ekstensi.

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
}
Andrey Frolov
sumber
Bagaimana jika Anda ingin mempertimbangkan nullsebagai true?
Thibault Falise
IsTrue () | IsNull () .. :) Saya mereproduksi logika bagaimana SQL bekerja dengan nulls. Saya pikir ini adalah sintaks yang paling bersih dan dapat dimengerti.
Andrey Frolov
Seharusnya bool statis publik IsFalse (System ini. Val yang dapat dihapus) {return! Val ?? benar; } untuk menganggap null sebagai salah
Michael Freidgeim
2
Mungkin ada titik koma (;) dalam dua metode terakhir (yaitu IsNull, dan IsNotNull)
glenn garson
4

Mari kita periksa bagaimana perbandingan dengan null didefinisikan:

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}");
    }

dan hasilnya adalah:

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

Jadi Anda dapat menggunakan:

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

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

// check if true or false
if (nullable != null) ...
Sz. Moncz
sumber
Saya hanya ingin tahu mengapa kita tidak bisa melakukan jika (nullable) .... itu akan ditangani tetapi perlu diperlakukan dengan hatiif(nullable)...else if(!nulllable)...else..
IronHide
Saya akan mengatakan selama tahun-tahun terakhir gaya pengkodean (karena ketersediaan alat-alat seperti stylecop, analyzer, dll.) Lebih dan lebih suka kode yang tidak ambigu, jelas, "niat mengkonfirmasikan" (misalnya merekomendasikan untuk menggunakan tanda kurung yang tidak dibutuhkan hanya untuk mengkonfirmasi penggunaan yang dimaksud prioritas operator, atau menggunakan berbagai sistem anotasi / kontrak). IMO yang memperkenalkan sintaksis semacam itu akan menimbulkan lebih banyak kebingungan karena tingkat ketidakjelasan bagaimana penanganan nullables daripada manfaat.
Sz. Moncz
4

Sebenarnya saya pikir itu (nullableBool ?? false)adalah pilihan yang sah terutama ketika Anda mencoba untuk mengevaluasi bool nullable di LINQ.

Sebagai contoh:
array.Select(v => v.nullableBool ?? false)
(from v in array where v.nullableBool ?? false)

Lebih bersih menurut saya dibandingkan dengan:
array.Select(v => v.nullableBool.HasValue ? v.nullableBool.Value : false)
(from v in array where v.nullableBool.HasValue ? v.nullableBool.Value : false)

Zze
sumber
1

Jika Anda hanya ingin menguji untuk truemenentang null/ false, Satu saya baru saja menggunakan dan membaca dengan baik adalah

bool? someCondition = null
if (someCondition.Equals(true))
...
ds4940
sumber
1
Apakah Anda tidak mendapatkan pengecualian referensi nol di sini?
Chase Florell
@ChaseFlorell Saya harus mengecek ini di VS Interactive window .. Jadi yang perlu diingat adalah bahwa jenis kondisi adalah Nullable <bool>. Anda masih dapat memanggil metode yang diwarisi dari objek (seperti Persamaan), HasValue dan GetValueOrDefault , tetapi tidak Nilai
ds4940
menarik, saya bisa melihatnya sekarang. Masih samar untuk jenis referensi dotnetfiddle.net/8cAI21
Chase Florell
0

Saya pikir itu terserah Anda. Saya tentu berpikir pendekatan .HasValue lebih mudah dibaca, terutama dengan pengembang yang tidak terbiasa dengan ?? sintaksis.

Poin lain dari tipe boolean yang dapat dibatalkan adalah bahwa itu adalah tristate, jadi Anda mungkin ingin melakukan sesuatu yang lain ketika itu hanya nol, dan bukan default ke false.

James Westgate
sumber
0

Diberikan enum

public enum PublishMode { Edit, View }

Anda dapat melakukannya seperti di sini

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

//or
       if (mode?? PublishMode.Edit == someValue)
       ....
    }
Menggali
sumber
Bukan jawaban untuk pertanyaan, yang secara khusus tentang nullable boolean.
ToolmakerSteve
0

Jika Anda berada dalam situasi di mana Anda tidak memiliki kendali atas apakah bagian dari kondisi memeriksa nilai yang dapat dibatalkan, Anda selalu dapat mencoba yang berikut ini:

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

Saya tahu ini bukan pendekatan murni yang menempatkan terner dalam pernyataan if tetapi itu menyelesaikan masalah dengan bersih.

Ini, tentu saja, cara mengatakan secara manual GetValueOrDefault(false)

MetalPhoenix
sumber
3
Solusi yang disediakan dalam OP adalah hal yang sama, tetapi hanya dengan kode mengasapi jauh lebih sedikit. Ini sama sekali tidak menguntungkan untuk itu.
Servy