2009-05-26 3 views
80

System.Enumから派生した任意の型を対応する整数値に変換するための一般的なメソッドを作成したいと思います。System.Enumから基本整数に変換する方法ですか?

例えば、私が欲しいのはこのようなものです:

// Trivial example, not actually what I'm doing. 
class Converter 
{ 
    int ToInteger(System.Enum anEnum) 
    { 
     (int)anEnum; 
    } 
} 

しかし、これは動作するように表示されません。 Resharperは、 'System.Enum'型の式を 'int'型にキャストできないと報告しています。

今私はこの解決策を考え出しましたが、私はむしろより効率的なものを持っています。

class Converter 
{ 
    int ToInteger(System.Enum anEnum) 
    { 
     return int.Parse(anEnum.ToString("d")); 
    } 
} 

お勧めはありますか?

+1

私はResharperではなく、不平を言うコンパイラだと信じています。 – Kugel

+1

必ずしもそうではありません。 System.Enumに拡張メソッドがあり、Resharperが不平を言うことにしました。 'Some.Cool.Type.That.Is.An.Enum'を 'System.Enum'に変換できません 列挙型です。コンパイルしてコードを実行するとうまくいきます。 VSをシャットダウンしてResharperキャッシュを吹き飛ばし、それを元に戻すと、再スキャンが完了するとすべてが正常です。私にとっては、それはある種のキャッシュスナフです。彼のために同じかもしれない。 – Mir

+0

@私はこれにもReSharperに「不満」を与えました。私のための同じ修正。なぜこれらの型が混ざっているのか分かりませんが、コンパイラは間違いありません。 – akousmata

答えて

114

あなたはキャストしたくない場合は、

Convert.ToInt32() 

は、トリックを行うことができます。

ダイレクトキャスト((int)enumValue経由)はできません。列挙型が異なる基本型(int,longbyte ...)を持つことができるので、これもまた「危険」であることに注意してください。

正式

詳細:その後、System.Enum(いずれもValueTypeのですが)Int32と直接継承関係を持っていないので、明示的なキャストは、型システム

+2

'Converter.ToInteger(MyEnum.MyEnumConstant);'ここでエラーは発生しません。その部分を編集してください。 – nawfal

+0

THanks、@nawfal、あなたが正しいです。私はレスポンスを編集しました。基になる型が – MartinStettner

+0

が作動していません。 –

1

System.Enumからintへのキャストは、私にとってうまくいきます(MSDNにもあります)。おそらくそれはResharperのバグです。

+1

使用しているランタイムのバージョンは? – JoshBerke

+2

リンクは、 'System.Enum'自体ではなく、' System.Enum'のサブタイプのキャスティングを示しています。 – nawfal

+0

私が持っていたのと同様の問題は、Resharper cache snafuでした。 VSを閉じてResharperキャッシュを削除すると、フル再スキャンしてもエラーが消えました。 – Mir

34

以内に正しいことができない、私はそれがオブジェクトにキャストすることによって動作するようになったとint:

public static class EnumExtensions 
{ 
    public static int ToInt(this Enum enumValue) 
    { 
     return (int)((object)enumValue); 
    } 
} 

これは醜い、おそらく最良の方法ではありません。私はそれをつぶやき続けることができるかどうかを確認するために、私はもっと良いものを考え出すために...

編集:Convert.ToInt32それに。

public static class EnumExtensions 
{ 
    public static int ToInt(this Enum enumValue) 
    { 
     return Convert.ToInt32(enumValue); 
    } 
} 

テスト:

int x = DayOfWeek.Friday.ToInt(); 
Console.WriteLine(x); // results in 5 which is int value of Friday 

EDIT 2:コメントの中で、誰かがこれが唯一のC#3.0で動作することを述べました。私はちょうどこのようにVS2005でこれをテストし、それが働いた:

public static class Helpers 
{ 
    public static int ToInt(Enum enumValue) 
    { 
     return Convert.ToInt32(enumValue); 
    } 
} 

    static void Main(string[] args) 
    { 
     Console.WriteLine(Helpers.ToInt(DayOfWeek.Friday)); 
    } 
+0

int'私はあなたに1を与えたが、このソリューションが唯一のC#3.0以降で動作するように起こっている 'と異なる場合) – Vadim

+0

私はこれがコンパイラを満たしていると思います。実行時にこれをテストできましたか?私はこの機能にいかなる価値も渡すことができませんでした... – MartinStettner

+0

拡張メソッドなので?または、古いバージョンのC#でenumについて異なるものがありますか? – BFree

-1

は、列挙型自体はそれに静的なヘルパー関数の束を持っていることを忘れないでください。列挙型のインスタンスを対応する整数型に変換するだけなら、おそらく最も効率的な方法です。

Enumは特定の型の列挙型ではないので、ReSharperは不平を言っていると思います。列挙型自体は、Enumではなくスカラ型から派生しています。あなたは一般的な方法で適応キャストが必要な場合は、私はこれがあなたによく、スイートでしたと言うでしょう(列挙型自体も一般的な中に含まれていることに注意してください:

public static EnumHelpers 
{ 
    public static T Convert<T, E>(E enumValue) 
    { 
     return (T)enumValue; 
    } 
} 

これは、そのようにのように使用することができます:

public enum StopLight: int 
{ 
    Red = 1, 
    Yellow = 2, 
    Green = 3 
} 

// ... 

int myStoplightColor = EnumHelpers.Convert<int, StopLight>(StopLight.Red); 

私は私の頭の上から確かに言うことはできませんが、上記のコードでも、以下のことができ、C#の型推論によってサポートされる可能性があります:

int myStoplightColor = EnumHelpers.Convert<int>(StopLight.Red); 
+1

残念ながら、あなたの例ではEが可能いかなるタイプ。ジェネリックスでは、型パラメータの制約としてEnumを使用することはできません。 私が言うことができない:構造体、しかし:列挙型 – Vadim

+0

あなたはここで、Tを使用することができます:T を。そのないあなたはそれになりたいが、それはあなたが使用することができます(私はあなたがやろうとするものであると考えている。) – jrista

+0

任意の参照型を切り出すと同じように、かなりのように厳密: を(typeof演算(E).IsEnum!)新しいスローする場合ArgumentException( "Eは列挙型でなければなりません"); – diadiora

11

は、なぜあなたは目を改革する必要がありますヘルパーメソッドとeのホイール? enumの値を基になる型にキャストすることは完全に合法です。

それは使用することが、より読み少ないタイピングだし、私の意見では...

int x = (int)DayOfWeek.Tuesday; 

...というよりも、何かのような...

int y = Converter.ToInteger(DayOfWeek.Tuesday); 
// or 
int z = DayOfWeek.Tuesday.ToInteger(); 
+4

すべてのenum値を変換したいです。つまり、いくつかのコードで一般的な方法で処理されている列挙型フィールドを持つさまざまなクラスがあります。これがintへの単純なキャストが適切でない理由です。 – orj

+0

@orj、あなたがどういう意味か分かりません。あなたは必要な使用法を示す例を挙げることができますか? – LukeH

+2

一般的なメソッドの場合など、列挙型を直接キャストできないことがあります。ジェネリックメソッドはenumに制限することができないので、structにint型にキャストできないものに制限しています。その場合、Convert.ToInt32(enum)を使用してそれを行うことができます。 –

4

私の答えhereから:

のようにeを考える:

Enum e = Question.Role; 
そして、これらの作品

は:

int i = Convert.ToInt32(e); 
int i = (int)(object)e; 
int i = (int)Enum.Parse(e.GetType(), e.ToString()); 
int i = (int)Enum.ToObject(e.GetType(), e); 

最後の二つは平野醜いです。最初のものはより読みやすいはずですが、2番目の方がはるかに高速です。または、拡張方法かもしれませんが、両方の世界の最高の最高です。

public static int GetIntValue(this Enum e) 
{ 
    return e.GetValue<int>(); 
} 

public static T GetValue<T>(this Enum e) where T : struct, IComparable, IFormattable, IConvertible, IComparable<T>, IEquatable<T> 
{ 
    return (T)(object)e; 
} 

今、あなたは呼び出すことができます。

e.GetValue<int>(); //or 
e.GetIntValue(); 
+0

もう1つは高速ですか?私はそれがボックスに列挙し、intに戻ってunboxと仮定しますか? – yoyo

+1

@yoyo 'e'変数には、すでに実際の値型、つまり列挙型のボックス化されたインスタンスがあります。 'Enum e = Question.Role; 'と書くと、すでにボックス化されています。問題は、ボックス化された 'System.Enum'を元のint型(unboxing)に戻すことです。だからここでは、unboxingはパフォーマンス上の懸念だけです。 '(int)(object)e'はダイレクトunbox呼び出しです。他のアプローチよりも速くなければなりません。 [これを参照してください](http://stackoverflow.com/questions/7995606/boxing-occurrence-in-c-sharp) – nawfal

+0

説明をありがとう。私は、System.Enumのインスタンスがunboxed値であると誤解していました。これも参照してください - http://msdn.microsoft.com/en-us/library/aa691158(v=vs.71).aspx – yoyo

8

を使用すると、その基になる型(全てではない列挙型は、intが付いています)を使用することができますにあらゆる列挙型を変換する必要がある場合:

return System.Convert.ChangeType(
    enumValue, 
    Enum.GetUnderlyingType(enumValue.GetType())); 
+4

これは唯一の防弾応答です。 –

+0

これは間違いなく受け入れられる回答であるはずです。 –

関連する問題