Czy typy enum .NET są rzeczywiście zmiennymi typami wartości?
Patrząc z refleksją na pola typu wyliczeniowego, zauważyłem ku mojemu zdziwieniu, że pole instancji „kopii zapasowej”, która zawiera rzeczywistą wartość określonego wystąpienia wyliczenia, nie jestprivate
, jak myślałem, alepublic
. I tak nie byłoreadonly
zarówno. (IsPublic
prawdziwe,IsInitOnly
fałszywy.)
Wiele osób uważa „zmienne” typy wartości w systemie typu .NET za „złe”dlaczego są typy wyliczeniowe (jak na przykład z kodu C #)tylko to?
Teraz, jak się okazuje, kompilator C # ma pewien rodzaj magii, która zaprzecza istnieniu pola instancji publicznej (ale patrz poniżej), ale np. W PowerShell możesz to zrobić:
prompt> $d = [DayOfWeek]::Thursday
prompt> $d
Thursday
prompt> $d.value__ = 6
prompt> $d
Saturday
Polevalue__
może być zapisany.
Teraz, aby to zrobić w C #, musiałem użyćdynamic
ponieważ wydaje się, że przy normalnym powiązaniu elementu w czasie kompilacji, C # udaje, żepublic
pole instancji nie istnieje. Oczywiście do użyciadynamic
, będziemy musieli użyćboks 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ę, że komentarze mówią same za siebie. Możemy zmutować instancję typu wyliczeniowegoDayOfWeek
(może być dowolnym typem wyliczeniowym z zespołu BCL lub z zespołu „domowego”) przez apublic
pole. Ponieważ instancja znajdowała się w tablicy hashtable, a mutacja doprowadziła do zmiany kodu skrótu, instancja znajduje się w niewłaściwym „wiadrze” po mutacji, aHashSet<>
nie może działać.
Dlaczego projektanci .NET zdecydowali się utworzyć pole instancji typów wyliczeniowychpublic
?