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)

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


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)) {
}

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.


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) { ... }

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

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
}

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) ...

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)


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))
...

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.


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)
       ....
    }

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)


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 é
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.