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 ::

  1. Perché non riesco a unboxing StringComparison? Credo che questo è perché è il tipo di fondo è Int32 ma io ancora trovo strano.
  2. 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.

È stato utile?

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 dovrebbe funzionare anche. E 'un po' poco chiaro se entrambi devono lavorare o entrambi dovrebbero fallire. La specifica dice che

  

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.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top