2011-12-30 5 views
5

私は列挙型が定数としてコンパイルされていることを理解しています。そのため、列挙型を変更すると大きな変化が生じます。なぜ私はEnumsが静的なreadonly変数が代わりに同じ方法でコンパイルされていないのだろうと思っていますか?なぜ列挙型は静的な値ではなく定数としてコンパイルされましたか?

+1

実行時にconstの値と同じように値を変更することはできません。それらが静的であれば、その価値が変わる可能性があることを意味します。 –

答えて

6

これらはフィールドよりも効率的であるため、ILに直接埋め込むことができる場合と同じ方法でコンパイルする必要はありません。

[Enums]は、const値がロードされるのと同じ方法でロードされます。これらは、ILの に直接埋め込まれています。一方、フィールドは、パフォーマンスにいくらか影響を与えるフィールドロード命令 (ldsfld)を必要とします。したがって、列挙型は典型的な使用法ではconstと同じくらい速く です。フィールドはやや遅くなります。

Source

+0

さて、パフォーマンスベースの決定だった。これはまさに私が探していたものです... "なぜ?"への答え。 –

1

enum (C# Reference)

からわずか任意の定数と同様に、 の個々の値列挙へのすべての参照は

コンパイル時に数値リテラルに変換され

何か不足していますか?

+0

はい。問題は「静的な読み込みの代わりに定数としてコンパイルされるのはなぜですか? ...基本的に、静的な読み込みの代わりに定数リテラルにするというデザインの決定はどうでしたか?私は間違っていないです場合 –

+0

@my、読み取り専用インスタンスに設定され、インスタンス化 –

8

両方の回答は技術的には正しいものの、統計的に異なる定数(読取り専用)については説明がありません。 C#では、定数は常に速く読み取り専用よりも、その理由は非常にシンプルで、最高の小さなコード例で表現:

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 
} 

コンパイル時に、コンパイラは、その定数の実際の値に定数へのすべての参照を置き換え。コンパイル時に定数をあらかじめ定義しなければならないので、そうすることができます。これは静的ではあるが実行時に実際に解決される静的読み取り値とは異なります。以下の例を見てみましょう:GB2132は、実際にこのコードを実行するように意図されているマシンに存在する場合、コンパイラが知る方法はありません

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

。この値を解決する唯一の方法は、実行時です。 Staticは、値そのものがインスタンスの存続期間にバインドされていないことを保証し、読み取り専用で値が一度しか設定されないことを保証します。コンパイラがこのフィールドへの参照をコンパイル時に置き換える方法はありません。値を単に知ることができないからです。

論理的には、プリミティブ型だけを定数としてマークできます。

現在、列挙型の場合は非常に簡単です。列挙型は、整数値以上のものです。したがって、次のコード:

enum MyEnum 
{ 
    First, 
    Second, 
    Third 
} 

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

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

はにコンパイラによって解決されます:ターンに一定のフィールドへの実際の参照を意味

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 
    } 
} 

を作り、コンパイル時に既知の値に置き換えることができますコードの最終版は次のようになります。

static void Main() 
{ 
    int test = 0; 

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

恐ろしい説明、男 – ivowiblo

+0

いやに設定できない定数と同じではありませんが、列挙型が変更を壊している理由の質問はありませんでしたが、することができますMicrosoftが静的な読み取り専用フィールドではなく定数としてそれらをコンパイルする理由を説明しました。彼らは、コンパイラはどちらかの道を行く機会があったことは、破壊の変更だろうと、疑問は、なぜ彼らが代わりに定数で行きましたし、誰かが単にパフォーマンス向上のために...それに答えました。 –

関連する問題