Melhor maneira de verificar se há bool anulável em uma expressão de condição (se ...)

208

Eu queria saber qual era a sintaxe mais limpa e compreensível para fazer verificações de condição em bools anuláveis.

O seguinte estilo de codificação é bom ou ruim? Existe uma maneira de expressar a condição melhor / mais limpa?

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

especialmente a parte if (nullableBool ?? false) . Eu não gosto do if (x.HasValue && x.Value)estilo ...

(não tenho certeza se a pergunta foi feita antes ... não foi possível encontrar algo semelhante com a pesquisa)

FireSnake
fonte

Respostas:

362

Eu acho que muitas pessoas se concentram no fato de que esse valor é anulável e não pensam no que elas realmente querem :)

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

Ou se você quiser mais opções ...

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

(nullableBool == true)nunca retornará verdadeiro se o bool? é nulo: P

Artiom Chilaru
fonte
2
Não percebi que a comparação anulável era significativa assim. Detalhes podem ser encontrados em msdn.microsoft.com/en-us/library/2cf62fcy.aspx
Micah Zoltu
79

Que tal usar GetValueOrDefault , que é bastante autoexplicativo e permite usar o padrão que você deseja:

if (nullableBool.GetValueOrDefault(false)) {
}
Lucero
fonte
6
Dependendo do contexto que essa abordagem pode gerarSystem.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
Eu gosto dessa abordagem, pois também funciona em uma declaração não-if (ou seja, atribuição).
paultechguy
48

Você pode não gostar, mas pessoalmente acho

if (x.HasValue && x.Value)

o mais legível. Isso deixa claro que você está trabalhando com um tipo anulável e deixa claro que você está primeiro verificando se o tipo anulável tem um valor antes de agir condicionalmente.

Se você pegar sua versão e substituir a variável por x, também será exibido:

if (x ?? false)

Isso é tão claro? É óbvio que x é um tipo anulável? Eu vou deixar você decidir.

Dan Diplo
fonte
Até onde sei, ?? funciona apenas em tipos anuláveis. Além disso, a variável deve ter um nome mais agradável do que x :)
firesnake
5
Por "tipo anulável", eu quis dizer especificamente tipos System.Nullable. Qualquer tipo de referência pode ser nulo. Além disso, se você precisar usar o tipo de uma variável como parte de seu nome, isso é indicativo de que seu código não está claro.
quer
@DanDiplo Como escrever UT para isso?
Prashant Yadav
xé bom no contexto e às vezes é mais limpo; saber:var openOrders = orders.Where(x=>x.Open ?? false)
nothingisnecessary
21

Se você deseja tratar a nullcomo false, então eu diria que a maneira mais sucinta de fazer isso é usar o operador de coalescência nula ( ??), como você descreve:

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

Basta pensar em bool? como tendo 3 valores, as coisas ficam mais fáceis:

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

fonte
8

Use extensões.

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
fonte
E se você quiser considerar nullcomo true?
Thibault Falise
IsTrue () | IsNull () .. :) Reproduzi a lógica de como o SQL funciona com valores nulos. Eu acho que é a sintaxe mais limpa e compreensível.
Andrey Frolov
Deve ser público IsFalse bool estático (este System.Nullable val) {return! Val ?? verdade; } considerar nulo como falso
Michael Freidgeim em 22/08/2010
2
Pode estar faltando ponto e vírgula (;) nos últimos dois métodos (ou seja IsNull, e IsNotNull)
Glenn garson
4

Vamos verificar como a comparação com nulo é definida:

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

e os resultados são:

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

Então você pode usar com segurança:

// 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
fonte
Im apenas querendo saber por que não podemos fazer se (anulável) .... que seria punho, mas precisam ser tratadas com cautelaif(nullable)...else if(!nulllable)...else..
Ironhide
Eu diria que, nos últimos anos, o estilo de codificação (devido à disponibilidade de ferramentas como stylecop, analisadores, etc.) prefere cada vez mais códigos claros, inequívocos e "confirmadores de intenção" (por exemplo, recomendar o uso de parênteses desnecessários apenas para confirmar o uso pretendido prioridade dos operadores ou usando vários sistemas de anotação / contrato). A introdução dessa sintaxe pela IMO causaria muito mais confusão devido ao nível de clareza de como os nulos são tratados do que os benefícios.
Sz. Moncz 17/05/19
4

Na verdade, acho que (nullableBool ?? false)é uma opção legítima, especialmente quando você está tentando avaliar um bool anulável no linq.

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

É mais limpo na minha opinião, em oposição a:
array.Select(v => v.nullableBool.HasValue ? v.nullableBool.Value : false)
(from v in array where v.nullableBool.HasValue ? v.nullableBool.Value : false)

Zze
fonte
1

Se você quiser apenas para teste truecontra o null/ false, único que eu acabo usado e lê muito bem é

bool? someCondition = null
if (someCondition.Equals(true))
...
ds4940
fonte
1
Você não está recebendo uma exceção de referência nula aqui?
Chase Florell
@ChaseFlorell Eu tive que checar isso na janela do VS Interactive. Portanto, o importante é lembrar que o tipo de condição é Nullable <bool>. Você ainda pode chamar os métodos herdados do objeto (como Equals), HasValue e GetValueOrDefault , mas não o valor
ds4940 26/02
interessante, eu posso ver isso agora. Ainda esboçado para tipos de referência dotnetfiddle.net/8cAI21
Chase Florell 26/02
0

Eu acho que depende de você. Eu certamente acho que a abordagem .HasValue é mais legível, especialmente com desenvolvedores não familiarizados com o ?? sintaxe.

O outro ponto de um tipo booleano anulável é que ele é tristate; portanto, você pode fazer outra coisa quando for apenas nulo e não usar como padrão false.

James Westgate
fonte
0

Dado enum

public enum PublishMode { Edit, View }

você pode fazer isso aqui

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

//or
       if (mode?? PublishMode.Edit == someValue)
       ....
    }
Gopher
fonte
Não é uma resposta para a pergunta, que é especificamente sobre nullable boolean.
Página
0

Se você estiver em uma situação em que não tem controle sobre se parte da condição está verificando um valor anulável, sempre pode tentar o seguinte:

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

Eu sei que não é exatamente uma abordagem purista colocar um ternário em uma declaração if, mas resolve o problema de maneira limpa.

Esta é, obviamente, uma maneira manual de dizer GetValueOrDefault(false)

MetalPhoenix
fonte
3
A solução fornecida no OP é a mesma coisa, mas com muito menos inchaço no código. Isso não é de todo vantajoso para isso.
precisa saber é