Perché ci sono sia una variazione di cortocircuito OR sia una variazione in cortocircuito di quell'operatore in C #?

9

Periodicamente, mi domando su questo:

Il cortocircuito OR restituirebbe sempre lo stesso valore che avrebbe l'operatore OR in cortocircuito.

Mi aspetto che il cortocircuito OR possa sempre valutare più rapidamente. Quindi, l'operatore OR non circoscritto incluso nel linguaggio C # per coerenza?

Che cosa ho perso?

    
posta CarneyCode 25.12.2011 - 09:01
fonte

5 risposte

25

Entrambi gli operandi erano pensati per cose diverse, provenienti da C che non aveva un tipo booleano. La versione di cortocircuito || funziona solo con i booleani, mentre la versione non a corto circuito | funziona con tipi interi, eseguendo un bit a bit o. È appena successo di funzionare come operazione logica non a corto circuito per i booleani rappresentati da un singolo bit, essendo 0 o 1.

link

    
risposta data 25.12.2011 - 09:58
fonte
13

| (bitwise-o) deve essere non-corto-circuito per tipi come int . Questo perché in quasi tutti i casi è necessario calcolare entrambi i lati di un'espressione | per calcolare il risultato corretto. Ad esempio, qual è il risultato di 7 | f(x) ?

Se f(x) non viene valutato, non puoi dirlo.

Inoltre, sarebbe incoerente rendere questo operatore un cortocircuito per bool , quando non è in cortocircuito per int . A proposito, penso di non aver mai usato | per i confronti logici intenzionalmente, trovando che è molto sconveniente parlare di | come operatore logico.

|| tuttavia è per confronti logici, in cui la valutazione del cortocircuito funziona bene.

Lo stesso vale anche per C e C ++, dove è l'origine di quegli operatori.

    
risposta data 25.12.2011 - 10:00
fonte
5

Questo è corretto, l'operatore OR di cortocircuito (||) restituirà sempre lo stesso valore dell'operatore OR senza cortocircuito (|). (*)

Tuttavia, se il primo operando è true, l'operatore di cortocircuito non causerà la valutazione del secondo operando, mentre l'operatore senza cortocircuito causerà sempre la valutazione di entrambi gli operandi. Ciò può avere un impatto sulle prestazioni e, a volte, sugli effetti collaterali.

Quindi, c'è un uso per entrambi: se ti interessi per le prestazioni, e la valutazione del secondo operando non produce alcun effetto collaterale, (o se non ti interessa di loro), allora usa assolutamente il corto -circuito operatore. Ma se per qualche motivo hai bisogno degli effetti collaterali del secondo operando, allora dovresti usare l'operatore non a corto circuito.

Un esempio in cui dovresti usare l'operatore senza cortocircuito:

if( write_customer_to_database() != SUCCESS |
    write_supplier_to_database() != SUCCESS |
    write_order_to_database() != SUCCESS )
{
    transaction_rollback();
}

(*) Tranne per alcuni scenari realmente perversi in cui la valutazione del primo operando su false causa per effetto collaterale il secondo operando da valutare su true invece che su false.

    
risposta data 25.12.2011 - 09:46
fonte
4

Ci sarebbero 2 motivi per usare la variante senza cortocircuito:

  1. mantenere gli effetti collaterali (ma è più chiaro codificare con una variabile temporanea)

  2. neutralizza gli attacchi temporali evitando la forchetta del cortocircuito (questo potrebbe anche migliorare l'efficienza di runtime se il secondo operando è una variabile, ma questa è una micro-ottimizzazione che il compilatore può fare comunque)

risposta data 25.12.2011 - 13:01
fonte
2

se la clausola della mano destra dell'operatore ha un effetto collaterale e il programmatore intende che entrambi gli effetti collaterali avvengano prima di controllarne il valore di ritorno.

    
risposta data 25.12.2011 - 09:43
fonte

Leggi altre domande sui tag