Warum Unboxing Aufzählungen ungerade Ergebnisse liefern?
Frage
Sie sich die folgenden ::
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 Dinge ::
- Warum kann ich
StringComparison
unbox? Ich denke, das liegt daran, dass es zugrunde liegende Typ istInt32
ist, aber ich es immer noch seltsam finden. - Warum
nullableEnum
einen Wert von null hat?
Als ich die einzige gültige Unboxing ist von einem Box-Wert Typ verstehen ist, um es den Typ oder auf eine Nullable Type. Wenn int
Enum
unbox kann, dann tut, warum nicht die gleichen halten gilt für die Nullable-Werte? Und falls Statt boxed StringComparison.OrdinalIgnoreCase
von 5 ich, wäre es, dass nullableInt
sein null wäre, aber nullableEnum
wäre nicht.
Lösung
Genau genommen Ich denke, es ist ein Fehler in Implementierungsdetail von die Laufzeit, da die C # Spezifikation sagt
Unboxing zu einem NULL festlegbaren-Typ erzeugt den Nullwert des nullable-Typs, wenn der Quellenoperand null ist, oder der umhüllte Ergebnis unboxing die Objektinstanz zu dem zugrunde liegenden Typ des nullable Typs anders.
Das heißt, wenn auf StringComparison Unboxing funktioniert, dann Unboxing zu Nullable
Für eine Unboxing-Umwandlung in einen gegebenen nicht-nullable-Wert-Typ zur Laufzeit erfolgreich zu sein, den Wert des Quelloperand muss ein Verweis auf einen geschachtelte Wert dieses nicht-nullable-Wert-Typs sein.
Sie müssen entscheiden, ob eine Box int a betrachtet ist ein boxed Wert vom Typ StringComparison zu sein, weil der zugrunde liegende Typ von StringComparison int ist. Die Spezifikation geht weiter zu sagen, dass eine InvalidCastException ausgelöst wird, wenn die Box ein „inkompatibel Objekt“ enthält. Ein int ist sicherlich „kompatibel“ mit StringComparison, da Sie sicher die vier Bytes aus dem Heap in Ihre StringComparison Variable kopieren können.
Andere Tipps
Wenn Sie Enum oder integer zu Objekt geworfen, es hält immer noch Typinformationen. So wird box is StringComparison
false
zurück. Aber es darf jede Enum oder int einen Enum werfen, so explizite Umwandlung (StringComparison)box
funktioniert. Es ist ein besonderer Fall für Aufzählungen. Nullable<T>
, auf der anderen Seite, ist nur eine übliche Klasse ist T nicht in einer bestimmten Art und Weise behandelt, wenn Sie Check-Typen gegossen oder. Aus diesem Grunde ist dieser Code Ausnahme ausgelöst wird.
StringComparison? nullableEnum = (StringComparison?)nullableInt;
1) Ja, die Art der Enum zugrunde, int und deshalb funktioniert es auf diese Weise. Sogar mehr. Sie können Folgendes tun:
enum MyEnum { One = 1, Two = 2, } int i = 3; MyEnum myEnum = (MyEnum)i; // This works without exceptions.
2) Da StringComparison?
tatsächlich Nullable<StringComparison>
ist die andere Art ist. Und as
Betreiber nur überprüft, ob das Objekt des gleichen Typs wie in als Operator angegeben.