Patrząc, z odbiciem, na polach typu wyliczeniowego, zauważyłem ku mojemu zdziwieniu, że pole "zaplecza", które zawiera rzeczywistą wartość konkretnej instancji wyliczenia, to nie jest private
, jak myślałem, ale public
. I to też nie było. (IsPublic
prawda, IsInitOnly
fałszywe.)Czy typy wyliczeniowe .NET są właściwie zmiennymi typami wartości?
Wielu ludzi uważa „Zmienne” typy wartości w systemie typu NET „zło”, więc dlaczego są typy enum (jako stworzony z kodu C# na przykład) prostu ?
Teraz, jak się okazuje, kompilator C# ma jakąś magię, która zaprzecza istnieniu publicznego pola instancji (ale patrz poniżej), ale np. PowerShell możesz to zrobić:
prompt> $d = [DayOfWeek]::Thursday
prompt> $d
Thursday
prompt> $d.value__ = 6
prompt> $d
Saturday
Pole value__
można zapisać na.
Teraz, aby zrobić to w języku C#, musiałem użyć dynamic
, ponieważ wydaje się, że przy normalnym powiązaniu z członkiem kompilacji C# udaje, że pole instancji public
nie istnieje. Oczywiście do użycia dynamic
, będziemy musieli użyć boksowania wartości wyliczeniowej.
Oto przykład kodu C#:
// 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
myślę komentarze mówią same za siebie. Możemy zmutować instancję typu wyliczeniowego DayOfWeek
(może to być dowolny typ wyliczeniowy z zespołu BCL lub z zespołu "domowego") poprzez pole public
. Ponieważ instancja była w zmiennej hashtable, a mutacja prowadzi do zmiany kodu skrótu, instancja znajduje się w niewłaściwym "wiadrze" po mutacji, a funkcja HashSet<>
nie może działać.
Dlaczego projektanci .NET zdecydowali się na utworzenie pola instancji typu enum public
?
Zastanawiam się nad Waszymi pomysłami, co byłoby idealnym wdrożeniem. Czy chcesz się podzielić? –
W rzeczywistości istnieje znacznie prostszy sposób udowodnienia, że typy enum są zmienne, bez boksu i dynamiczne: https://gist.github.com/thomaslevesque/6100447 –
@KenKin Cóż, przede wszystkim, moim pomysłem jest, że pole instancji która utrzymuje, że rzeczywista wartość bieżącej instancji powinna być "prywatna". To, czy nazwa zawierałaby "zabawne" postacie (postacie niemożliwe w nazwach identyfikatorów w C#), czy nie, byłoby, moim zdaniem, mniej ważne. –