2011-12-30 19 views
5

Rozumiem, że wyliczenia są zestawiane jako stałe, więc ich zmiana powoduje przełomową zmianę. Zastanawiam się, dlaczego nie zostały one skompilowane w taki sam sposób, jak zamiast tego są statyczne zmienne readonly?Dlaczego wartości Enums zostały skompilowane jako stałe zamiast wartości statycznych?

+1

Wartości wyliczeń nie mogą zmieniać się w czasie wykonywania w taki sam sposób, jak przechyłki const.Gdyby były statyczne, co oznaczałoby, że ich wartość mogłaby się zmienić. –

Odpowiedz

6

Mogą być bardziej wydajne niż pola, więc nie ma potrzeby kompilowania ich w taki sam sposób, kiedy mogą być bezpośrednio osadzone w IL.

[Emisje] są ładowane w ten sam sposób, w jaki są ładowane wartości const. Są one osadzone bezpośrednio w IL. Z drugiej strony, Fields wymagają instrukcji obciążenia w terenie o nazwie (ldsfld), która w pewnym stopniu wpłynie na wydajność. W ten sposób wyliczenia są tak samo szybkie jak w typowym przypadku; pola są nieco wolniejsze.

(Source)

+0

Ok, więc to była decyzja oparta na wynikach. Właśnie tego szukałem ... odpowiedzi na pytanie "dlaczego?". –

1

Z enum (C# Reference)

Podobnie jak w przypadku stałej, wszystkie odniesienia do poszczególnych wartości wyliczenia są przekształcane literałach liczbowych w czasie kompilacji

Więc czegoś mi brakuje?

+0

Tak. Pytanie brzmiało: "Dlaczego są one kompilowane jako stałe zamiast statycznych readonly?" ... Zasadniczo, jaka była decyzja projektowa, aby stały się stałymi literałami zamiast statycznych readonly? –

+0

@my, jeśli się nie mylę, to tylko do odczytu można ustawić na tworzenie i nie jest to to samo, co stałe, których nie można ustawić na instancję –

8

Obie podane odpowiedzi są poprawne technicznie, ale brakuje im wyjaśnienia stałych różniących się statystyką (tylko do odczytu). W języku C#, Stałe są zawsze szybsze niż tylko do odczytu, a powód jest bardzo prosty, a najlepiej wyrażone z małym przykład kodu:

const int MyConstant = 10; 
static readonly int MyReadonly = 20; 

static void Main() 
{ 
    int result = MyConstant + MyReadonly; 
    // the above statement will be resolved to: 
    // int result = 10 + MyReadonly 
} 

W czasie kompilacji, kompilator zastępuje wszystkie odniesienia do stałej z rzeczywistej wartości tej stałej . Jest to możliwe, ponieważ stała musi być wstępnie zdefiniowana podczas kompilacji. Różni się to od statycznych wartości tylko do odczytu, które choć statyczne, są faktycznie rozwiązywane w czasie wykonywania. Weźmy następujący przykład:

static readonly Encoding = Encoding.GetEncoding("GB2132"); 

Nie ma sposobu, aby kompilator wiedzieć, czy rzeczywiście istnieje GB2132 na maszynie, na której kod ten jest przeznaczony do uruchomienia. Jedynym sposobem na rozwiązanie tej wartości jest uruchomienie. Statyczny zapewnia, że ​​sama wartość nie jest związana z czasem istnienia instancji i tylko w trybie odczytu zapewnia, że ​​wartość można ustawić tylko raz. Kompilator nie może zastąpić odniesień do tego pola w czasie kompilacji, ponieważ wartość nie może być znana.

Logicznie, tylko prymitywne typy mogą być oznaczone jako stałe.

Teraz w przypadku wyliczenia jest to bardzo proste. Wyliczenia są niczym więcej niż wartością całkowitą z etykietą. Więc następujący kod:

enum MyEnum 
{ 
    First, 
    Second, 
    Third 
} 

static void Main() 
{ 
    MyEnum test = MyEnum.First; 

    if (test == MyEnum.Second) 
    { 
     // whatever 
    } 
} 

będą rozstrzygane przez kompilator do:

const int MyEnum_First = 0; 
const int MyEnum_Second = 1; 
const int MyEnum_Third = 2; 

static void Main() 
{ 
    int test = MyEnum_First; 

    if (test == MyEnum_Second) 
    { 
     // whatever 
    } 
} 

co z kolei oznacza rzeczywiste odniesienia do stałych pól może zostać zastąpiona wartością znaną w czasie kompilacji, czyniąc końcowa wersja kodu coś w stylu:

static void Main() 
{ 
    int test = 0; 

    if (test == 1) 
    { 
     // whatever 
    } 
} 
+0

Niesamowite wytłumaczenie, koleś – ivowiblo

+0

Tak, ale pytanie nie było dlaczego Enums łamią zmiany, ale dlaczego Microsoft zdecydował się skompilować je jako stałe zamiast statycznych pól tylko do odczytu. Mogli kazać kompilatorowi pójść w obie strony, ale pytanie brzmiało: dlaczego używali stałych, gdy byłaby to przełomowa zmiana, a ktoś odpowiedział na to ... po prostu dla wydajności. –

Powiązane problemy