La mejor manera de verificar si hay bool anulable en una expresión de condición (si ...)

208

Me preguntaba cuál era la sintaxis más limpia y comprensible para hacer verificaciones de condición en las boletas anulables.

¿Es el siguiente estilo de codificación bueno o malo? ¿Hay alguna manera de expresar la condición mejor / más limpiamente?

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

especialmente la parte if (nullableBool ?? false) . No me gusta el if (x.HasValue && x.Value)estilo ...

(no estoy seguro si la pregunta se ha hecho antes ... no se pudo encontrar algo similar con la búsqueda)

Serpiente de fuego
fuente

Respuestas:

362

Creo que muchas personas se concentran en el hecho de que este valor es anulable, y no piensan en lo que realmente quieren :)

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

O si quieres más opciones ...

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

(nullableBool == true)nunca volverá cierto si el bool? es nulo: P

Artiom Chilaru
fuente
2
No me di cuenta de que la comparación anulable era significativa de esta manera. Los detalles se pueden encontrar en msdn.microsoft.com/en-us/library/2cf62fcy.aspx
Micah Zoltu
79

¿Qué tal usar GetValueOrDefault , que se explica por sí solo y permite usar el valor predeterminado que desee?

if (nullableBool.GetValueOrDefault(false)) {
}
Lucero
fuente
66
Dependiendo del contexto que pueda arrojar este enfoqueSystem.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
Me gusta este enfoque, ya que también funciona en una declaración no if (es decir, asignación).
paultechguy
48

Puede que no te guste, pero personalmente encuentro

if (x.HasValue && x.Value)

El más legible. Deja en claro que está trabajando con un tipo anulable y deja en claro que primero está verificando si el tipo anulable tiene un valor antes de actuar condicionalmente.

Si toma su versión y reemplaza la variable con x también se lee:

if (x ?? false)

¿Está eso tan claro? ¿Es obvio que x es un tipo anulable? Te dejaré decidir.

Dan Diplo
fuente
hasta donde se, ?? solo funciona en tipos anulables. Además, la variable debería tener un nombre más agradable que x :)
FireSnake
55
Por "tipo anulable" me refería específicamente a los tipos System.Nullable. Cualquier tipo de referencia puede ser nulo. Además, si necesita usar el tipo de una variable como parte de su nombre, entonces eso es indicativo de que su código no está claro.
Dan Diplo
@DanDiplo ¿Cómo escribir UT para esto?
Prashant Yadav
xestá bien en contexto y a veces es más limpio; a saber:var openOrders = orders.Where(x=>x.Open ?? false)
nothingisnecessary
21

Si desea tratar un nullcomo falso, entonces diría que la forma más sucinta de hacerlo es usar el operador de fusión nula ( ??), como usted describe:

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

Solo piensa en bool? teniendo 3 valores, entonces las cosas se vuelven más fáciles:

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

fuente
8

Usa extensiones.

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
fuente
¿Qué pasa si quieres considerar nullcomo true?
Thibault Falise
IsTrue () | IsNull () .. :) Reproduje la lógica de cómo funciona SQL con nulos. Creo que es la sintaxis más limpia y comprensible.
Andrey Frolov
Debe ser public static bool IsFalse (este System.Nullable val) {return! Val ?? cierto; } considerar nulo como falso
Michael Freidgeim
2
Pueden faltar puntos y comas (;) en los dos últimos métodos (es decir, IsNull e IsNotNull)
glenn garson
4

Veamos cómo se define la comparación con nulo:

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

y los resultados son:

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

Para que pueda usar con seguridad:

// 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
fuente
Estoy preguntando por qué no podemos hacer si (anulable) .... que sería mango, pero deben ser tratados con precauciónif(nullable)...else if(!nulllable)...else..
Ironhide
Diría que durante los últimos años el estilo de codificación (debido a la disponibilidad de herramientas como stylecop, analizadores, etc.) prefiere cada vez más el código inequívoco, claro y de "confirmación de intención" (por ejemplo, recomienda utilizar paréntesis innecesarios solo para confirmar el uso previsto). de prioridad de los operadores, o usando varios sistemas de anotación / contrato). La introducción de una sintaxis de este tipo en la OMI causaría mucha más confusión debido al nivel de falta de claridad en la forma en que se manejan los valores anulables que en el beneficio.
Sz. Moncz
4

En realidad, creo que (nullableBool ?? false)es una opción legítima, especialmente cuando intentas evaluar un bool anulable en linq.

Por ejemplo:
array.Select(v => v.nullableBool ?? false)
(from v in array where v.nullableBool ?? false)

Es más limpio en mi opinión en lugar de:
array.Select(v => v.nullableBool.HasValue ? v.nullableBool.Value : false)
(from v in array where v.nullableBool.HasValue ? v.nullableBool.Value : false)

Zze
fuente
1

Si solo quieres probar truecontra null/ false, uno que acabo de usar y lee bastante bien es

bool? someCondition = null
if (someCondition.Equals(true))
...
ds4940
fuente
1
¿No está obteniendo una excepción de referencia nula aquí?
Chase Florell
@ChaseFlorell Tuve que verificar esto en la ventana VS Interactive. Entonces, lo que hay que recordar es que el tipo de alguna condición es Nullable <bool>. Todavía puede llamar a los métodos heredados del objeto (como Equals), HasValue y GetValueOrDefault , pero no Valor
ds4940
interesante, puedo ver eso ahora. Todavía incompleto para los tipos de referencia dotnetfiddle.net/8cAI21
Chase Florell
0

Creo que depende de ti. Ciertamente creo que el enfoque .HasValue es más legible, especialmente con los desarrolladores que no están familiarizados con el ?? sintaxis.

El otro punto de un tipo booleano anulable es que es triestado, por lo que es posible que desee hacer algo más cuando es simplemente nulo y no predeterminado a falso.

James Westgate
fuente
0

Enum dado

public enum PublishMode { Edit, View }

puedes hacerlo como aquí

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

//or
       if (mode?? PublishMode.Edit == someValue)
       ....
    }
Ardilla de tierra
fuente
No es una respuesta a la pregunta, que trata específicamente nullable boolean.
ToolmakerSteve
0

Si se encuentra en una situación en la que no tiene control sobre si parte de la condición está verificando un valor anulable, siempre puede intentar lo siguiente:

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

Sé que no es exactamente un enfoque purista poner un ternario en una declaración if, pero resuelve el problema limpiamente.

Esta es, por supuesto, una forma manual de decir GetValueOrDefault(false)

MetalPhoenix
fuente
3
La solución provista en el OP es la misma, pero con mucha menos extensión de código. Esto no es nada ventajoso para eso.
Servy