2010-11-25 6 views
1

リフレクションで列挙型の値を設定すると、ちょっと変わった動作が発生しました。リフレクションで無効なEnum値を割り当てることができます

 EnumReflector e = new EnumReflector(); 
     e.Test(); 
     if (e.TheEnum == EnumReflector.MyEnum.Option1 || 
      e.TheEnum == EnumReflector.MyEnum.Option2 || 
      e.TheEnum == EnumReflector.MyEnum.Option3) 
     { 
      Console.WriteLine("Value is valid"); 
     } 
     else 
     { 
      Console.WriteLine("Value is invalid: {0} ({1})", e.TheEnum.ToString(), (int)e.TheEnum); 
     } 

出力がされています:

値が無効である私はこれを呼び出した場合、

class EnumReflector 
{ 
    public enum MyEnum 
    { 
     Option1 = 0, 
     Option2, 
     Option3 
    } 

    public MyEnum TheEnum { get; set; } 

    public void Test() 
    { 
     PropertyInfo pi = this.GetType().GetProperty("TheEnum"); 
     string badValue = "1234"; 
     object propertyValue = Enum.Parse(pi.PropertyType, badValue, true); 

     pi.SetValue(this, propertyValue, null); 
    } 
} 

今:私は列挙型のため、無効な値を設定することができるよように思えます:1234(1234)

これはどのようにすることができますか?私はenumの本質の1つが制限された価値のあるセットですが、

答えて

5

列挙型は、(定義可能な整数プリミティブ型の)整数であり、定義された名前付き定数で定義されています。名前付き定数を持たない値を代入する必要はありません。

enum MyEnum { 
    None, One, Two 
} 

MyEnum e = (MyEnum)100; 

コンパイルが正常に動作します。これが、Enum.IsDefined()静的メソッドの理由でもあります。これは、enum値が定義済みの値かどうかをチェックします。

+0

もちろん。 IsDefined()チップのおかげで – Ive

0

実際には、列挙型は値が厳密に設定されていますが、コンパイル時には値が設定されます。このリフレクションの欠点は、コンパイラが提供するすべてのコンパイル時チェックを緩和し、独自の責任のために値を操作することです。

+1

彼らがさえコンパイル時に制限されていない - あなたは、リフレクションを使用せずに同じ効果を得るために '(MyEnum)1234'を書くことができます。 –

0

あなたも、反射に頼る必要はありません。

EnumReflector e = new EnumReflector(); 

e.TheEnum = (EnumReflector.MyEnum)1234; 

if (e.TheEnum == EnumReflector.MyEnum.Option1 || 
    e.TheEnum == EnumReflector.MyEnum.Option2 || 
    e.TheEnum == EnumReflector.MyEnum.Option3) 
{ 
    Console.WriteLine("Value is valid"); 
} 
else 
{ 
    Console.WriteLine("Value is invalid: {0} ({1})", 
         e.TheEnum.ToString(), (int)e.TheEnum); 
} 
関連する問題