Pourquoi énumérations unboxing donnent des résultats bizarres?
Question
Considérez le suivant ::
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 choses ::
- Pourquoi puis-je Unbox
StringComparison
? Je suppose que cela est dû au fait qu'il est le type sous-jacent estInt32
mais je trouve toujours bizarre. - Pourquoi
nullableEnum
ont une valeur nulle?
Si je comprends bien le unboxing ne valide est d'un type de valeur est boxed type de ou à un type Nullable. Si int
peut Unbox Enum
, alors pourquoi ne pas le même vrai pour les valeurs nullables? De même, si au lieu de 5 je StringComparison.OrdinalIgnoreCase
boxed, ce serait que nullableInt
serait nulle, mais nullableEnum
ne serait pas.
La solution
Strictement parlant, je pense que c'est une bug dans voir la mise en œuvre de le moteur d'exécution, étant donné que la spécification C # dit
Unboxing à un type nullable produit la valeur nulle du type nullable si la source opérande est nul, ou le résultat enveloppé de unboxing l'instance d'objet du type sous-jacent du type nullable autrement.
Ainsi, si unboxing à StringComparison fonctionne, unboxing alors Nullable
Pour une conversion unboxing à un non annulable valeur de type donné pour réussir à l'exécution, la valeur de la source opérande doit être une référence à une valeur boxed de cette non-annulable valeur type.
Vous devez décider si un int est un boxed considéré comme une valeur de type boîte StringComparison parce que le type sous-jacent de StringComparison est int. La spécification poursuit en disant qu'une InvalidCastException est levée si la boîte contient un « objet incompatible ». Un int est certainement « compatible » avec StringComparison, parce que vous pouvez en toute sécurité les copier quatre octets à partir du tas dans votre variable StringComparison.
Autres conseils
Quand vous lancez ENUM ou entier à l'objet, il détient toujours des informations de type. Alors box is StringComparison
retournera false
. Mais il est permis de jeter tout ou enum int à tout ENUM, donc des œuvres de (StringComparison)box
explicites de la distribution. Il est un cas particulier pour les énumérations. Nullable<T>
, d'autre part, est juste une classe ordinaire, T ne sont pas traités de quelque façon spécifique lorsque vous lancez ou le type de contrôle. Voilà pourquoi ce code lancera une exception.
StringComparison? nullableEnum = (StringComparison?)nullableInt;
1) Oui, le type de ENUM sous-jacente est int et qui est pourquoi cela fonctionne de cette façon. Encore plus. Vous pouvez faire ce qui suit:
enum MyEnum { One = 1, Two = 2, } int i = 3; MyEnum myEnum = (MyEnum)i; // This works without exceptions.
2) Parce que StringComparison?
est en fait Nullable<StringComparison>
de type différent. Et opérateur as
vérifie uniquement si l'objet est du même type que celui spécifié en tant qu'opérateur.