2014-09-11 16 views
18

Forse sono nelle basi, ma sto ancora studiando questa cosa di C# a scuola. Capisco che se aggiungo 1 al valore intero con valore massimo, quale è 32 bit, il risultato sarà negativo. Ho letto che C# offre parole chiave selezionate e non selezionate per gestire gli overflow. La parola chiave verificata è qualcosa che ho trovato utile, ma che ne dici di una parola chiave non controllata? Non riesco davvero a trovare un uso poco utile per il blocco non scritto di parole chiave. C'è qualche? In che modo i prossimi due approcci differiscono gli uni dagli altri?deselezionata -keyword in C#

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 

namespace Practice_6 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      int value = Int32.MaxValue; 
      value++; 
      //Approach 1 to make a decision 
      if (value > Int32.MaxValue) { 
       //Do something 
      } 
      value = Int32.MaxValue; 
      //Approach 2 to make a decision 
      unchecked { 
       value++; 
       //Do something 
      } 
      //What's the difference between these two approaches to handle overflow? 
    } 
} 
+0

'if (value> Int32.MaxValue)' --- questa condizione dovrebbe essere vera per alcuni valori "interi"? – zerkms

+1

Le implementazioni personalizzate di 'GetHashCode' sono buoni esempi di scenari in cui' deselezionata' può essere utile, ovvero http://stackoverflow.com/a/263416/1644813 –

+0

se (valore> INT32.MaxValue) ritorna True, penso –

risposta

4

io non sono del tutto sicuro di implicazioni sulle prestazioni di checked e unchecked. In teoria, unchecked dovrebbe essere più performante ed è il contesto predefinito. A meno che non si aggiri i limiti dei tipi interi per un qualche tipo di algoritmo/logica aziendale, ecc., L'uso di checked è raramente necessario/utile/leggibile.

Come ho detto, unchecked è il contesto predefinito, quindi perché è necessaria una parola chiave unchecked? Una cosa potrebbe essere essere espliciti riguardo al tipo di contesto in cui è presente un uso elevato dei contesti checked. L'altro è quello di utilizzare unchecked contesto all'interno checked contesto:

checked { 
    int a = 5 + 1231; 

    unchecked { 
     a += 221; 
    } 
} 

La tua domanda potrebbe essere il motivo per cui il contesto predefinito sia selezionata. Immagino sia una scelta di design di Microsoft.

La differenza è che i controlli di contesto checked in caso di overflow per ciascuna operazione aritmetica e solleva un'eccezione in caso di overflow.

+0

+1 per rispondere alla domanda effettiva – har07

2

da MSDN la ragione per l'utilizzo incontrollato sarebbe la seguente

Perché il controllo di troppo pieno richiede tempo, l'uso del codice incontrollato in situazioni in cui non v'è alcun pericolo di troppo pieno potrebbe migliorare le prestazioni. Tuttavia, se l'overflow è una possibilità, deve essere utilizzato un ambiente controllato.

+0

Mentre le informazioni citate potrebbero essere utili in un certo senso, penso che OP abbia chiesto quando è utile la parola chiave 'unchecked' perché il contesto predefinito è già 'deselezionato', e questo non risponde alla domanda – har07

+0

Non è necessariamente il default se/controllato è usato, di solito, ma non in tutti i casi –

0

modificare i codici a:

int value = int.MaxValue; 
    unchecked 
    { 
    value++; 
    } 
    Console.WriteLine(value); 
    value = int.MaxValue; 
    checked 
    { 
    value++; // this will raise OverflowException 
    } 

e vedrete la differenza.

+0

Questo non risponde alla domanda. La domanda riguarda la differenza tra * usando 'deselezionata * * e * non usando alcuna parola chiave * – har07

+2

_non usare qualsiasi parola chiave_ potrebbe essere simile a _utilizzare checked_ o _using unschecked_, a seconda delle impostazioni del compilatore. Vedi http://msdn.microsoft.com/en-us/library/khy08726.aspx –

30

AGGIORNAMENTO: Questa domanda era the subject of my blog in April 2015; grazie per la domanda interessante!


La tua prima domanda è:

Il checked parola chiave è utile, ma come circa la parola chiave unchecked? Non riesco davvero a trovarne un uso. C'è qualche?

Il team di progettazione C# non ha l'abitudine di aggiungere funzionalità che non sono utili alla lingua. (Con la notevole eccezione dell'operatore unario più, l'operatore più inutile del mondo.)

La parola chiave non selezionata ha due casi d'uso principali.

Innanzitutto, l'aritmetica dei numeri interi costanti è sempre selezionata per impostazione predefinita. . Questo può essere irritante.Supponiamo per esempio di avere un codice di interoperabilità e si desidera creare una costante per il HRESULT_E_FAIL:

const int E_FAIL = 0x80004005; 

Questo è un errore perché quel numero è troppo grande per essere in un int. Ma potresti non voler usare uno uint. Si potrebbe pensare così mi limiterò a dire

const int E_FAIL = (int)0x80004005; 

, ma che è anche illegale perché costante aritmetica tra cui conversioni è sempre selezionata per impostazione predefinita.

Quello che devi fare è disattivare controllata costante aritmetica via

const int E_FAIL = unchecked((int)0x80004005); 

In secondo luogo, l'aritmetica di default per non costante matematica intero in C# non è selezionata, perché è più veloce, e perché questo è quello che molti altre lingue simili. Tuttavia C# consente di modificare l'impostazione predefinita per l'aritmetica controllata per la matematica dei numeri interi non costanti tramite un flag del compilatore. Se lo hai fatto, e devi disattivarlo di nuovo temporaneamente, devi utilizzare la sintassi del blocco o dell'espressione unchecked.

Un terzo caso d'uso consiste nell'utilizzare il blocco non controllato come una forma di codice di auto-documentazione, per dire "Sono consapevole che l'operazione che sto facendo qui potrebbe traboccare, e che per me va bene." Per esempio, io scrivo spesso qualcosa di simile:

int GetHashCode() 
{ 
    unchecked 
    { 
     int fooCode = this.foo == null ? 0 : this.foo.GetHashCode(); 
     int barCode = this.bar == null ? 0 : this.bar.GetHashCode(); 
     return fooCode + 17 * barCode; 
    } 
} 

Il "incontrollato", sottolinea al lettore che ci aspettiamo che la moltiplicazione e l'aggiunta di codici hash potrebbero traboccare, e che questo è OK.

tua seconda domanda è:

Qual è la differenza tra questi due approcci per gestire troppo pieno?

Buona domanda.

Se nel vostro contesto selezionato intendete: Mi aspetto che l'aritmetica sia sempre entro i limiti; se non lo è, il mio programma ha un bug grave e deve essere terminato prima che faccia più danno al mondo quindi non si dovrebbe fare alcun controllo di overflow, perché non ci sono overflow. Qualsiasi eccezione dovrebbe terminare il programma; il contesto controllato sta semplicemente facendo funzionare il runtime per verificare la correttezza del codice.

Se nel vostro contesto controllato intendi mi richiedono l'aritmetica di essere all'interno dei limiti, ma ho ottenuto questi dati da una fonte inaffidabile e io sono troppo pigro per fare il controllo dei limiti su di esso allora si dovrebbe intercettare l'eccezione. Tuttavia,, la soluzione migliore sarebbe eseguire il controllo dell'intervallo e fornire un errore più significativo se i dati sono fuori intervallo, piuttosto che fare in modo che il runtime noti il ​​problema e generare un'eccezione di overflow. Raccomando vivamente il controllo della portata piuttosto che prendere un'eccezione; non essere pigro.

+0

La mia preferenza con 'deselezionata 'sarebbe di focalizzarla il più strettamente possibile (solo l'ultima espressione). C'è qualche ragione particolare per favorire un ambito più ampio? Inoltre, se uno è ad es. accettare dati da un file binario che ad es. contiene una combinazione di valori base e relativi, che cosa ci si aspetta che il codice faccia se la somma di un valore relativo e l'overflow di base? Se lo scenario più plausibile in cui ciò si verificherebbe, qualcuno avrebbe tentato di caricare un file di tipo sbagliato (il che significa che il file e tutti i dati letti finora dovrebbero essere considerati privi di significato, ma il sistema va bene) ... – supercat

+0

.. .quali sono le differenze pratiche tra l'eccezione di un'eccezione oltre a OverflowException, l'intercettazione di OverflowException e il lancio di qualcos'altro, il lancio di OverflowException e l'attesa del chiamante per supporre che OverflowException implichi un tentativo di caricare qualcosa che non era un file valido del tipo previsto o che lasciava si verifica una OverflowException (con la stessa aspettativa per il chiamante)? – supercat

+6

+1 per menzionare l'inutilità dell'operatore più unario –

4

Il codice scritto correttamente non dovrebbe dipendere dal fatto che un progetto sia compilato con selezionato o deselezionato come predefinito. Il codice in cui il comportamento aritmetico di avvolgimento imprevisto può comportare rischi per la sicurezza o la stabilità del sistema deve essere eseguito in un contesto checked. Il codice che si basa sull'elaborazione del comportamento aritmetico deve essere eseguito in un contesto unchecked.Il codice di uso generale in cui non è previsto che si verifichino overflow aritmetici, ma avrebbe conseguenze limitate se lo facessero, dovrebbe essere compilato utilizzando l'impostazione a livello di progetto. L'impostazione del livello del progetto può quindi essere impostata su selezionata o deselezionata come compromesso tra velocità di esecuzione e intercettazione degli errori tempestiva.

Se non si verificano overflow imprevisti, il codice verrà eseguito più velocemente in modalità non selezionata. Se, tuttavia, alcuni calcoli stanno producendo valori falsi e non è chiaro il motivo, può essere utile ricompilare con il controllo di overflow abilitato. Farà funzionare il codice più lentamente, ma intrappolerà il primo calcolo errato. La commutazione del progetto in modalità controllata per tale scopo, tuttavia, sarà possibile solo se quelle parti del progetto che si basano sul comportamento aritmetico di avvolgimento vengono eseguite in un contesto esplicito unchecked. In caso contrario, la commutazione delle modalità a livello di progetto interromperà semplicemente il programma.

Problemi correlati