Perché enumerazioni unboxing danno i risultati dispari?
Domanda
Si consideri il seguente ::
Object box = 5;
int @int = (int)box; // int = 5
int? nullableInt = box as int?; // nullableInt = 5;
StringComparison @enum = (StringComparison)box; // enum = OrdinalIgnoreCase
StringComparison? nullableEnum = box as StringComparison?; // nullableEnum = null.
2 cose ::
- Perché non riesco a unboxing
StringComparison
? Credo che questo è perché è il tipo di fondo èInt32
ma io ancora trovo strano. - Perché
nullableEnum
hanno un valore di null?
Per quanto ho capito l'unboxing unico valido è compreso tra un tipo di valore in scatola è ad esso di tipo o di un tipo nullable. Se int
può unboxing per Enum
, allora perché non fa la stessa valere per i valori Null? Allo stesso modo, se invece di 5 I StringComparison.OrdinalIgnoreCase
in scatola, sarebbe che nullableInt
sarebbe nulla, ma nullableEnum
non sarebbe.
Soluzione
A rigor di termini Penso che sia un bug dettaglio di implementazione di il runtime, dal momento che il C # spec dice
Unboxing di un tipo nullable produce il valore nullo del tipo nullable se la sorgente operando è nullo, o il risultato avvolto di spacchettamento istanza di oggetto di tipo sottostante di nullable tipo altrimenti.
Cioè, se unboxing a StringComparison funziona, allora unboxing per Nullable
Per una conversione unboxing a un dato non annullabile-value-type per riuscire in fase di esecuzione, il valore della sorgente operando deve essere un riferimento a un valore scatolata che non annullabile-value-type.
Si deve decidere se un int boxed è considerato un valore in scatola del tipo StringComparison perché il tipo di fondo di StringComparison è int. Le specifiche continua a dire che un InvalidCastException viene generata se la scatola contiene un "oggetto incompatibile". Un int è sicuramente "compatibile" con StringComparison, perché è possibile copiare in modo sicuro i quattro byte dal mucchio nella vostra variabile StringComparison.
Altri suggerimenti
Quando lanci enum o intero a oggetto, che detiene ancora informazioni sul tipo. Così box is StringComparison
tornerà false
. Ma si è permesso di lanciare qualsiasi enum o int a qualsiasi enum, così esplicito del cast opere (StringComparison)box
. Si tratta di un caso speciale per le enumerazioni. Nullable<T>
, d'altra parte, è solo una classe di consueto, T non viene gestita in modo specifico quando lanci o il tipo di controllo. Questo è il motivo per cui questo codice genererà un'eccezione.
StringComparison? nullableEnum = (StringComparison?)nullableInt;
1) Sì, il tipo di enum sottostante è int e è per questo che funziona in questo modo. Ancora di più. Si può fare seguente:
enum MyEnum { One = 1, Two = 2, } int i = 3; MyEnum myEnum = (MyEnum)i; // This works without exceptions.
2) Poiché StringComparison?
è in realtà Nullable<StringComparison>
che è di tipo diverso. E operatore as
controlla solo se l'oggetto è dello stesso tipo, come specificato nella qualità di operatore.