16

Domanda rapida qui sulle istruzioni di cortocircuito in C#. Con un'istruzione if in questo modo:Valutazione dichiarazione di cortocircuito - è garantito? [C#]

if (MyObject.MyArray.Count == 0 || MyObject.MyArray[0].SomeValue == 0) 
{ 

//.... 
} 

E 'garantito che la valutazione si fermerà dopo la parte "MyArray.Count", a condizione che parte è vero? In caso contrario ricevo un'eccezione null nella seconda parte.

+1

Nel caso in cui si stia facendo questa domanda perché * ha * ottenuto un'eccezione di riferimento null dal codice precedente, è probabile perché 'MyArray' è nullo o' MyArray [0] 'contiene un valore nullo. Vedi la mia risposta. –

risposta

34

Sì, questo è garantito.

C# Language Specification - 7.11 Conditional logical operators:

I && e || operatori sono chiamati gli operatori logici condizionali. Sono anche chiamati operatori logici "cortocircuiti".

Pertanto essi sosterranno logica corto circuito per definizione - si può contare su questo comportamento.

Ora è importante fare una distinzione tra un condizionale operatore e un operatore di logica:

  • Solo operatori condizionali sostegno a breve circuito, operatori logici non lo fanno.
  • Gli operatori logici di C# appaiono esattamente come le loro controparti condizionali ma con un carattere in meno, quindi un OR logico è | e un AND logico è &.
  • Gli operatori logici possono essere sovraccaricati ma gli operatori condizionali non possono (questo è un po 'tecnico dato che la valutazione dell'operatore condizionale comporta una risoluzione di sovraccarico e questa risoluzione di sovraccarico può risolversi in un sovraccarico personalizzato dell'operatore logico del tipo, quindi è possibile aggirare questo limitazione in una certa misura).
+1

+1 per quotare effettivamente il CLS. – Polynomial

5

Sì, è garantito, ma è comunque possibile ottenere un'eccezione di riferimento null se MyArray è nullo (o MyObject ovviamente).

0

preferisco usare l'operatore & &, perché allora il test di un positivo (il mio array contiene elementi), piuttosto che negativo (il mio errore non contiene elementi):

if (MyObject.MyArray.Count > 0 && MyObject.MyArray[0].SomeValue == 0) 
{ 

//.... 
} 

Questa è garantita anche a corto circuito.

+0

Il risultato di questo codice non è lo stesso del suo, però. Nel suo, se il conteggio è 0, si mette in cortocircuito ed entra nel blocco. Nel tuo, * solo * inserisce il blocco sul valore del primo elemento pari a 0. –

2

Solo una piccola osservazione.

Lei ha detto questo:

Altrimenti vado a prendere un un'eccezione nulla nella seconda parte. (sottolinea il mio)

Questo non è vero, in realtà. Se il cortocircuito non fosse garantito, potresti ottenere un IndexOutOfRangeException nella seconda parte.

E 'ancora possibile, si potrebbe ottenere un NullReferenceException, se il primo elemento nella oggetto è in realtà nulla (o se uno qualsiasi degli altri oggetti in quell'espressione sono).

L'unica totalmente controllo di sicurezza sarebbe questo:

bool conditionHolds = 
    MyObject == null || 
    MyObject.MyArray == null || 
    MyObject.MyArray.Count == 0 || 
    MyObject.MyArray[0] == null || 
    MyObject.MyArray[0].SomeValue == 0; 

if (conditionHolds) 
{ 
    //.... 
} 
+1

Penso che tu: if (! ConditionHolds) – riffnl

+0

@riffnl: No, stavo solo rendendo il mio esempio coerente con il codice dell'OP. (Sembra che voglia che il codice faccia qualcosa in caso negativo). –

2

Sì,

Per le operazioni AND se uno degli operandi è risultata falsa espressione poi totale è risultata falsa poi c'è non è necessario valutare le restanti espressioni, E in caso di operazione OR se uno qualsiasi degli operandi viene valutato su true, è possibile saltare la valutazione rimanente

Quindi utilizzando & & o || operatore, l'intera espressione può essere valutata come vera o falsa senza valutare tutte le espressioni secondarie.

Ma considera anche il suo side effect. This article potrebbe essere utile per comprendere la valutazione del cortocircuito in profondità con alcuni esempi reali.

Problemi correlati