Editar: Comentarios en la parte inferior. Además, this.¿Cómo es que una enumeración deriva de System.Enum y es un número entero al mismo tiempo?
Esto es lo que me confunde. Mi opinión es que si tengo una enumeración como esto ...
enum Animal
{
Dog,
Cat
}
... lo que en esencia lo que he hecho está definido un valor de tipo llamada Animal
con dos valores definidos, Dog
y Cat
. Este tipo deriva del tipo de referencia System.Enum
(algo que los tipos de valores normalmente no pueden hacer, al menos no en C#, pero que está permitido en este caso), y tiene una función para enviar y recibir valores de int
.
Si el camino que acabo de describir el tipo de enumeración anterior fuera cierto, entonces yo esperaría que el siguiente código para lanzar un InvalidCastException
:
public class Program
{
public static void Main(string[] args)
{
// Box it.
object animal = Animal.Dog;
// Unbox it. How are these both successful?
int i = (int)animal;
Enum e = (Enum)animal;
// Prints "0".
Console.WriteLine(i);
// Prints "Dog".
Console.WriteLine(e);
}
}
Normalmente, you cannot unbox a value type from System.Object
as anything other than its exact type. Entonces, ¿cómo es posible lo anterior? Es como si el tipo Animal
se un int
(no sólo convertibles a int
) y es unEnum
(no sólo convertibles a Enum
) al mismo tiempo.
¿Es herencia múltiple? ¿
System.Enum
de alguna manera hereda de
System.Int32
(algo que no esperaba que fuera posible)?
Editar: No puede ser cualquiera de los anteriores. El código siguiente muestra esto (creo) de manera concluyente:
object animal = Animal.Dog;
Console.WriteLine(animal is Enum);
Console.WriteLine(animal is int);
Las salidas anteriores:
True False
Tanto the MSDN documentation on enumerations y la especificación de C# hacer uso de la expresión "tipo subyacente"; pero no sé lo que esto significa, ni lo he escuchado usar en referencia a cualquier cosa que no sea enumeraciones. ¿Qué significa "tipo subyacente" en realidad que significa?
Entonces, ¿es este otro case that gets special treatment from the CLR?
Mi dinero es en ese caso ... pero una respuesta/explicación sería agradable.
actualización: Damien_The_Unbeliever proporcionan la referencia a responder realmente a esta pregunta. La explicación se puede encontrar en la Partición II de la especificación CLI, en la sección en enumeraciones:
Para propósitos de vinculación (p., para localizando una definición de método a partir de la referencia de método utilizada para llamarlo) enumeraciones debe ser distinta de su tipo subyacente . Para todos los demás propósitos de , incluida la verificación y la ejecución del código, una enumeración no incluida interconvierte libremente con su tipo subyacente. Enumeraciones pueden ser encajonados correspondiente a un tipo de instancia en caja , pero este tipo es no la misma como el tipo de caja de la tipo subyacente, por lo que el boxeo no pierde la tipo original de la enumeración.
Editar (de nuevo ?!): Espera, en realidad, no sé que leí que bien la primera vez. Quizás no explique al 100% el comportamiento de unboxing especializado en sí mismo (aunque estoy dejando la respuesta de Damien como aceptada, ya que arrojó mucha luz sobre este tema). Voy a seguir buscando en este ...
Otra Editar: Hombre, entonces yodaj007's answer me tiró para otro bucle. De alguna manera, una enumeración no es exactamente lo mismo que un int
; sin embargo, se puede asignar un int
a una variable enum sin conversión? Buh?
Creo que esto finalmente se ilumina con Hans's answer, y es por eso que lo acepté.
Información impresionante. Siento que aprendo 25 cosas nuevas cada vez que leo una de tus respuestas ... –
Hans Passant, pero ** ¿por qué eligieron "permitir que las enumeraciones y su tipo primitivo sean intercambiables" como dice el comentario en el código C++? Consulte mi nueva pregunta sobre el desempaquetado combinado y la conversión enum (mi pregunta está vinculada a esta pregunta anterior). –
El problema es que usted supone que la conversión de unboxing C# se comporta de la manera normal. Es lo opuesto, es la manera excepcional. Compruebe esta respuesta por la razón por la cual es excepcional: http://stackoverflow.com/questions/1583050/performance-surprise-with-as-and-nullable-types/3076525#3076525 –