2010-02-07 14 views
53

Sono un po 'perplesso da questo piccolo C# vezzo:L'operatore condizionale non può eseguire implicitamente l'esecuzione?

variabili Attribuite:

Boolean aBoolValue; 
Byte aByteValue; 

le seguenti compila:

if (aBoolValue) 
    aByteValue = 1; 
else 
    aByteValue = 0; 

Ma questo non lo farà:

aByteValue = aBoolValue ? 1 : 0; 

L'errore dice: "Impossibile convertire implicitamente il tipo 'int' in 'byte'."

E, naturalmente, questa mostruosità compilerà:

aByteValue = aBoolValue ? (byte)1 : (byte)0; 

Che cosa sta succedendo qui?

EDIT:

Utilizzando VS2008, C# 3.5

+0

possibile duplicato di [tipi Nullable e operatore ternario: perché è \? 10: null \ 'proibito?] (Http://stackoverflow.com/questions/858080/nullable-types-and-the-ternary-operator-why-is-10-null-forbidden) – nawfal

risposta

62

Questa è una domanda abbastanza frequente.

In C#, quasi sempre ragioniamo dall'interno all'esterno. Quando si vede

x = y; 

lavoriamo a ciò che è il tipo di x, qual è il tipo di y, e se il tipo di y è assegnazione compatibile con x. Ma non usiamo il fatto che sappiamo quale sia il tipo di x quando stiamo elaborando il tipo di y.

Questo perché ci potrebbe essere più di una x:

void M(int x) { } 
void M(string x) { } 
... 
M(y); // y is assigned to either int x or string x depending on the type of y 

Abbiamo necessità di essere in grado di capire il tipo di un'espressione senza sapere che cosa è stato assegnato.Digitare i flussi di informazioni out di un'espressione, non in un'espressione.

Per calcolare il tipo di espressione condizionale, calcoliamo il tipo di conseguenza e le espressioni alternative, selezioniamo il più generale dei due tipi e questo diventa il tipo di espressione condizionale. Pertanto, nell'esempio, il tipo di espressione condizionale è "int" e non è una costante (a meno che l'espressione di condizione non sia costante true o costante false). Poiché non è una costante, non puoi assegnarla a byte; il compilatore ragiona unicamente dai tipi, non dai valori, quando il risultato non è una costante.

L'eccezione a tutte queste regole è rappresentata dalle espressioni lambda, in cui il tipo di informazioni corrisponde al flusso dal lambda. Ottenere questa logica era molto difficile.

+2

La mia mente è saltata . Grazie, signore, questa è una parte illuminante e in due parti frustrante. Uno perché non può funzionare nel modo in cui * sembrerebbe * funzionare, e due perché ha senso che non possa funzionare in quel modo. Quindi ... costanti lo è! – MPelletier

+0

Grazie. Stavo cercando un post su questo argomento sul tuo blog, ma questo è ancora meglio. –

+0

@John: Parlo un po 'di questi problemi qui: http://blogs.msdn.com/ericlippert/archive/2006/05/24/type-inference-woes-part-one.aspx –

5

non possono avere una grande risposta per voi, ma se fate questo in molti luoghi, si potrebbe dichiarare:

private static readonly Byte valueZero = (byte)0; 
private static readonly Byte valueOne = (byte)1; 

e solo queste variabili Potresti farla franca usando const se è locale al progetto.

EDIT: usando readonly non avrebbe senso - questi non sono mai destinate a cambiare.

+0

Sono sicuro che era solo un refuso ma hai dichiarato la stessa variabile due volte. –

+1

@Hamish: capisco cosa intendi. Potrei usare const, ma è una soluzione. Questo certamente non merita il voto che hai ottenuto. – MPelletier

9

Sto utilizzando VS 2005, e posso riprodurre, per bool & booleana, ma non per vero

bool abool = true; 
Boolean aboolean = true; 
Byte by1 = (abool ? 1 : 2); //Cannot implicitly convert type 'int' to 'byte' 
Byte by2 = (aboolean ? 1 : 2); //Cannot implicitly convert type 'int' to 'byte' 
Byte by3 = (true ? 1 : 2);  //Warning: unreachable code ;) 

La soluzione più semplice sembra essere questo cast

Byte by1 = (Byte)(aboolean ? 1 : 2); 

Quindi, Sì, sembra che l'operatore ternario stia facendo sì che le costanti "correggano" i loro tipi come ints e disabilitino la conversione implicita del tipo che altrimenti si otterrebbe dalle costanti che si adattano al tipo più piccolo.

+0

+1 per fare un cast meno brutto del mio :) – MPelletier

+1

La tua spiegazione ha un senso. Ma perché le costanti non si fisserebbero in questa circostanza? E doppiamente curioso con la scoperta di Mendy. Qualcuno di Microsoft dovrebbe saperlo, e potrebbe essere necessario discuterlo con forza ... – MPelletier

+0

Penso che Mendy abbia scoperto che quando il compilatore può banalmente rilevare che può ottimizzare completamente l'operatore ternario, il codice di compilazione è uguale a 'Byte by = 2' che conserva la capacità di lanciare implicitamente. (vedi il mio commento sull'avvertimento del compilatore sopra) –

Problemi correlati