Modo ottimale per utilizzare operatori condizionali nulli nelle espressioni booleane

6

Stai scrivendo un'espressione booleana che potrebbe apparire come questa:

team.Category == "A Team" && team?.Manager?.IsVietnamVet

public class Manager
{
    public bool IsVietnamVet { get; set; }
}

public class Team
{
    public string Category { get; set; }

    public Manager Manager { get; set; }
}

... e ottieni un errore:

Operator '&&' cannot be applied to operands of type 'bool' and 'bool?'

Qual è il modo ottimale / più pulito per gestirlo?

  1. team.Category == "A Team" && (team?.Manager?.IsVietnamVet ?? false)

    È davvero leggibile?

  2. team.Category == "A Team" && (team?.Manager?.IsVietnamVet).GetValueOrDefault()

    Potrebbe non funzionare in LINQ-to-Entities ...

  3. team.Category == "A Team" && team?.Manager?.IsVietnamVet == true

    Scriveresti davvero if (condition == true) senza alcuna esitazione?

Ci sono altre opzioni? In definitiva è meglio scrivere:

  1. team.Category == "A Team" && team.Manager != null && team.Manager.IsVietnamVet
posta Santhos 24.03.2016 - 23:56
fonte

4 risposte

3

In questo caso particolare, potrebbe essere saggio seguire la Legge di Demeter i.e.

public class Team
{
    public bool IsManagerVietnamVet => Manager?.IsVietnamVet ?? false;
}    

Più in generale, se un'espressione booleana è complessa o brutta, non c'è nulla da dire che non puoi dividerlo (o parte di esso) in un'istruzione separata:

bool isVietnamVet = Manager?.IsVietnamVet ?? false;

if (team.Category == "A Team" && isVietnamVet)

Quando si passa attraverso il codice nel debugger, è spesso più bello avere condizioni elaborate racchiuse in un singolo bool solo per salvare un po 'di passaggio del mouseover; infatti, potrebbe essere più bello mettere l'intera cosa in una variabile bool .

bool isVietnamVetAndCategoryA = (team.Category == "A Team"
    && Manager?.IsVietnamVet ?? false);

if (isVietnamVetAndCategoryA)

o con LINQ:

var wibble = from flight in airport
             from passenger in flight.manifest
             let isOnPlane = 
                 (flight.FinishedBoarding && passenger.Flight == flight.FlightNumber)
             where !isOnPlane
             select passenger;
    
risposta data 27.03.2016 - 20:41
fonte
3

Espandendo la risposta di Ben Cottrell, il modello "Null Object" può aiutarti ulteriormente.

Invece di restituire un null team / manager, estrai ITeam e IManager interfacce e restituisci implementazioni alternative significative:

public class NoManager : IManager
{
    public bool IsVietnamVet => false;
}

public class NoTeam : ITeam
{
    public bool ManagedByVietnamVet => false;

    public IManager Manager => new NoManager();
}

Quindi all'improvviso puoi fare team.ManagedByVietnamVet in sicurezza.

Questo ovviamente si basa sul provider upstream di team per essere nullo-sicuro, ma ciò può essere garantito con test appropriati.

    
risposta data 29.09.2017 - 09:31
fonte
2

Penso che l'opzione 3 (cioè == true ) sia il modo più pulito per testare che un bool? è true , perché è molto chiaro su ciò che fa.

Nella maggior parte del codice x == true non ha senso, perché è lo stesso di x , ma non si applica qui, quindi penso che == true non sarebbe molto confuso.

    
risposta data 27.03.2016 - 20:21
fonte
-4

Ho scritto una semplice lezione che puoi usare:

 public class MyBool 
    {
        public bool? Value { get; set; }

        public MyBool(bool b)
        {
            Value = b;
        }

        public MyBool(bool? b)
        {
            Value = b;
        }

        public static implicit operator bool(MyBool m)
        {
            return m?.Value ?? false;
        }

        public static implicit operator bool?(MyBool m)
        {
            return m?.Value;
        }

        public static implicit operator MyBool(bool m)
        {
            return new MyBool(m);
        }

        public static implicit operator MyBool(bool? m)
        {
            return new MyBool(m);
        }

        public override string ToString()
        {
            return Value.ToString();
        }
    }

Se è affidabile utilizzare un tipo personalizzato, ovviamente. Puoi confrontare MyBool con bool e Nullable<bool> .

    
risposta data 25.03.2016 - 03:56
fonte

Leggi altre domande sui tag