Mit Nachdenken, in den Feldern eines Enum-Typs, bemerkte ich zu meiner Überraschung, dass das "Backing" -Instanzfeld, das den tatsächlichen Wert einer bestimmten Instanz des Enums enthält, nicht private
ist, wie ich gedacht hätte, aber public
. Und es war auch nicht readonly
. (IsPublic
wahr, IsInitOnly
false.)Sind .NET-Enum-Typen tatsächlich veränderbare Wertetypen?
Viele Menschen „wandelbar“ Wertetypen in .NET-Typ-System „Übel“ betrachten, so warum sind die Aufzählungstypen (von C# -Code zum Beispiel erstellt) nur, dass ?
Nun, wie sich herausstellt, hat der C# -Compiler eine Art von Magie, die die Existenz des öffentlichen Instanzfeldes bestreitet (aber siehe unten), aber z. Powershell Sie können dies tun:
prompt> $d = [DayOfWeek]::Thursday
prompt> $d
Thursday
prompt> $d.value__ = 6
prompt> $d
Saturday
Das Feld value__
geschrieben werden kann.
Nun, um dies in C# zu tun, musste ich dynamic
verwenden, weil es scheint, dass mit der normalen Compilierungszeit Memberbindung C# vorgibt, dass die public
Instanz Feld nicht existiert. Um dynamic
zu verwenden, müssen wir boxen des Enum-Werts verwenden.
Hier ist ein C# Codebeispiel:
// create a single box for all of this example
Enum box = DayOfWeek.Thursday;
// add box to a hash set
var hs = new HashSet<Enum> { box, };
// make a dynamic reference to the same box
dynamic boxDyn = box;
// see and modify the public instance field
Console.WriteLine(boxDyn.value__); // 4
boxDyn.value__ = 6;
Console.WriteLine(boxDyn.value__); // 6 now
// write out box
Console.WriteLine(box); // Saturday, not Thursday
// see if box can be found inside our hash set
Console.WriteLine(hs.Contains(box)); // False
// we know box is in there
Console.WriteLine(object.ReferenceEquals(hs.Single(), box)); // True
Ich denke, die Kommentare sprechen für sich. Wir können eine Instanz des Aufzählungstyps DayOfWeek
(kann ein beliebiger Aufzählungstyp von einer BCL-Assembly oder von einer "hausgemachten" Assembly sein) durch ein public
Feld mutieren. Da die Instanz in einer Hashtabelle war und die Mutation zu einer Änderung des Hash-Codes führte, befindet sich die Instanz nach der Mutation im falschen "Bucket" und die HashSet<>
kann nicht funktionieren.
Warum haben die Designer von .NET entschieden, das Instanzfeld von Enum-Typen public
zu machen?
Ich frage mich über Sie Ideen, was wäre eine ideale Umsetzung. Bist du bereit zu teilen? –
Eigentlich gibt es einen viel einfacheren Weg zu beweisen, dass Enum-Typen veränderbar sind, ohne Boxen oder dynamisch: https://gist.github.com/thomaslevesque/6100447 –
@KenKin Nun, vor allem ist meine Idee, dass die Instanz Feld das hält den tatsächlichen Wert der aktuellen Instanz sollte "privat" sein. Ob der Name "witzige" Zeichen enthält (Zeichen, die in C# nicht in identischen Namen vorkommen) oder nicht, wäre meiner Meinung nach weniger wichtig. –