AND è migliore o utilizza "IF" interno [duplicato]

8

In una situazione come questa: "

if ((metadata != null) && (metadata.TypeEnum != VariantInfoMetadata.CellTypeEnum.Status))

consigli di mantenere il codice così come è sopra? O è meglio creare un'istruzione "if" annidata e suddividere la condizione in due sezioni in cui "outer if" assicura che i metadati non siano nulli e interiori se fa il resto del controllo. Penso che un annidato si prenda cura dell'eventuale eccezione di riferimento null se il valore dei metadati diventa nullo.

    
posta Blake 29.10.2012 - 23:05
fonte

8 risposte

11

Il && e il || in molte lingue (C, C ++, Java, C #) sono cortocircuiti , il che significa che non appena la risposta è nota, smette di valutare. Se la tua lingua è uno dei linguaggi di cortocircuito, non è necessario un% co_de nidificato, poiché non appena if viene valutato a metadata != null , la valutazione dell'espressione generale si interromperà, impedendo il riferimento null. In effetti, il cortocircuito (logico) false s e AND s sono stati inventati appositamente per affrontare situazioni come te descritte senza la necessità di creare un ulteriore livello di nidificazione.

    
risposta data 29.10.2012 - 23:13
fonte
18

Quello che hai lì è perfetto. È chiaro e semplice.

Se avessi diversi casi di test per null, li combinerei. Questo è un problema in quanto verifica ripetutamente (metadata != null) .

if ((metadata != null) && (metadata.TypeEnum != CellTypeEnum.Status))
{ ... }
else if ((metadata != null) && (metadata.TypeEnum != CellTypeEnum.Info))
{ ... }
else if ((metadata != null) && (metadata.TypeEnum != CellTypeEnum.Blank))
{ ... }

Questo è meglio:

if (metadata != null)
{
    if (metadata.TypeEnum != CellTypeEnum.Status)
    { ... }
    else if (metadata.TypeEnum != CellTypeEnum.Info)
    { ... }
    else if (metadata.TypeEnum != CellTypeEnum.Blank)
    { ... }
}

O ancora meglio per l'enumerazione:

if (metadata != null)
{
    switch (metadata.TypeEnum) {
        case CellTypeEnum.Status:
            //do stuff
            break;
        case CellTypeEnum.Info:
            //do stuff
            break;
        case CellTypeEnum.Blank:
            //do stuff
            break;
    }
}
    
risposta data 29.10.2012 - 23:42
fonte
6

Un altro approccio consiste nell'utilizzare il schema Null Object .

Invece di controlli espliciti per null, restituisci sempre un'istanza, quindi in questo caso avresti (pseudo-codice):

public class NullMetadata
{
    VariantInfoMetadata TypeEnum { get; set; }

    public NullMetadata()
    {
        TypeEnum = VariantInfoMetadata.None
    }
}

Quindi anziché

var metadata = null

avresti

var metadata = new NullMetadata()

E il controllo per VariantInfoMetadata.CellTypeEnum.Status restituirebbe sempre false.

    
risposta data 29.10.2012 - 23:25
fonte
1

Preferisco mantenere le dichiarazioni all'interno di una clausola if quanto più concisa possibile, molte volte limitante li alle variabili booleane con nomi significativi, come ad esempio:

bool isCellTypeStatus = //...
if (isCellTypeStatus) { ... }

E la dichiarazione della variabile booleana coprirà più di una linea in modo che la messa a fuoco dell'occhio del programmatore non si trasformi in personaggi lontani.

bool isCellTypeStatus = 
       metadata != null &&
       metadata.TypeEnum != VariantInfoMetadata.CellTypeEnum.Status;

Separa due valutazioni mentali della condizione e del risultato, a due dichiarazioni separate, aumentando così la velocità di un altro programmatore consuma il tuo codice

    
risposta data 29.10.2012 - 23:28
fonte
1

Un altro fattore da aggiungere a dasblinkenlight (che penso sia la migliore risposta) Potrei aggiungere che è più leggibile per inserire frasi in un singolo se non nidificato, se le regole sono soggette a errori

    
risposta data 29.10.2012 - 23:34
fonte
1

A causa della valutazione del cortocircuito, entrambe le soluzioni sono valide anche dal punto di vista tecnico. Tuttavia, stilisticamente, di solito è preferibile e possibile organizzare variabili come metadata mai essere null in primo luogo.

In questo caso particolare, stai usando due variabili per denotare il tipo. metadata.TypeEnum memorizza il tipo e metadata essendo null indica un tipo "nessun metadata". Il tuo linguaggio di programmazione ti consente di creare tutti i tipi che desideri. Approfittane.

Una soluzione migliore è creare una classe base Cell che non abbia nemmeno un membro metadata , quindi non c'è bisogno che sia sempre null . Quindi crea una classe derivata StatusCell che aggiunge le proprietà univoche necessarie e la stessa per gli altri tipi di celle.

Se questo tipo di refactoring non è possibile, come se si stesse lavorando con un'API di terze parti, un'altra opzione da considerare è una clausola di guardia, come:

if (metadata == null)
    return;

if (metadata.TypeEnum != VariantInfoMetadata.CellTypeEnum.Status)
    ...

Molte persone (me compreso) preferiscono questo stile perché limita sia il livello di nidificazione che il numero di condizioni in un'istruzione if .

    
risposta data 30.10.2012 - 06:05
fonte
0

In breve, per il linguaggio C # è meglio tenerlo così com'è.

La valutazione della tua affermazione menzionata si fermerà e otterrai false valore una volta metadata is null .

Le istruzioni nidificate sono difficili da mantenere ed è preferibile ignorarle se la logica dell'applicazione non le richiede. In altre parole, potrebbero esserci diversi modi per formulare le istruzioni nidificate if in una sintassi più leggibile e gestibile.

    
risposta data 30.10.2012 - 00:17
fonte
0

Se ci sono più condizioni per un "successo", lo preferisco se le condizioni sono controllate in un blocco if , piuttosto che in istruzioni annidate.

Ma .....

Per la leggibilità a volte preferisco questo:

isOfOAge = age >= 16;
isSober = bloodAchohol = 0; // this calculated is wasteful if 'isOfOAge' is false
canDrive = isOfAge && isSober;
if(canDrive).......

La leggibilità rende un controllo dispendioso su isSober anche se isOfAGe è falso. Supponendo che i calcoli booleani siano molto costosi, una percentuale nidificata di co_de potrebbe fornire nomi di variabili piacevoli oltre all'effetto di cortocircuito.

La mia raccomandazione è NON metterla in uno standard di codifica. Non è sbagliato nidificare. Non è sbagliato usare il cortocircuito. Entrambi potrebbero portare a una migliore leggibilità in determinate situazioni.

    
risposta data 29.10.2012 - 23:58
fonte

Leggi altre domande sui tag