¿Por qué enumeraciones unboxing dan resultados impares?
Pregunta
Considere el siguiente ::
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 cosas ::
- ¿Por qué puedo desempacar a
StringComparison
? Supongo que esto se debe a que es el tipo subyacente seInt32
pero todavía me resulta extraño. - ¿Por qué
nullableEnum
tiene un valor de null?
A mi entender el unboxing solamente válido es de un tipo de valor en caja es a su tipo o de un tipo anulable. Si int
puede desempacar a Enum
, entonces ¿por qué no hace lo mismo es cierto para los valores anulables? Del mismo modo, si en lugar de 5 I StringComparison.OrdinalIgnoreCase
en caja, sería que nullableInt
sería nula, pero no sería nullableEnum
.
Solución
En sentido estricto Creo que es un error en detalle de implementación de el tiempo de ejecución, ya que la especificación C # dice
Unboxing a un tipo anulable produce el valor nulo de la de tipo anulable si la fuente operando es nulo, o el resultado envuelto de unboxing la instancia del objeto al tipo subyacente de la de tipo anulable lo contrario.
Es decir, si unboxing a StringComparison funciona, entonces unboxing a anulable
Para una conversión unboxing a una de tipo no anulable-valor dado para tener éxito en tiempo de ejecución, el valor de la fuente de operando debe ser una referencia a un valor en caja de que la no-de tipo valor anulable.
Usted tiene que decidir si un int en caja es un considerado como un valor en caja de tipo StringComparison porque el tipo subyacente de StringComparison es int. La especificación continúa diciendo que un InvalidCastException se produce si la caja contiene un "objeto incompatibles". Un int es ciertamente "compatible" con StringComparison, porque se puede copiar de forma segura los cuatro bytes de la pila en su variable de StringComparison.
Otros consejos
Cuando lanzas enumeración o entero a objeto, que sigue siendo válida la información de tipo. Así box is StringComparison
volverá false
. Pero se le permite lanzar cualquier enumeración o int a cualquier enumeración, por lo que las obras (StringComparison)box
conversión explícita. Es un caso especial para las enumeraciones. Nullable<T>
, por el contrario, es sólo una clase habitual, T no es manejado de ninguna manera específica cuando lanzas o escribe el cheque. Es por esto que este código arrojará una excepción.
StringComparison? nullableEnum = (StringComparison?)nullableInt;
1) Sí, el tipo de enumeración subyacente es de tipo int y que de por qué funciona de esta manera. Aún más. Puede hacer lo siguiente:
enum MyEnum { One = 1, Two = 2, } int i = 3; MyEnum myEnum = (MyEnum)i; // This works without exceptions.
2) Debido a StringComparison?
es en realidad Nullable<StringComparison>
que es de tipo diferente. Y operador as
sólo comprueba si el objeto es del mismo tipo como se especifica en como operador.