web-dev-qa-db-ja.com

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"));
    }
}

助言がありますか?

88
orj

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

Convert.ToInt32()

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

直接キャスト((int)enumValue経由)はできません。列挙型にはさまざまな基本型(intlongbyte...)があるため、これも「危険」であることに注意してください。

より正式には:System.EnumInt32と直接の継承関係を持たないため(両方ともValueTypesですが)、明示的なキャストは型システム内では正しくありません

129
MartinStettner

オブジェクトにキャストしてからintにキャストすることで動作するようになりました:

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

これは見苦しく、おそらく最善の方法ではありません。私はそれをいじり続け、より良いものを思い付くことができるかどうかを確認します。

編集:Convert.ToInt32(enumValue)が同様に機能することを投稿しようとしており、MartinStettnerが私にそれを打ち負かしたことに気付きました。

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

編集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));
    }
38
BFree

any enumをその基になる型に変換する必要がある場合(すべてのenumがintによってサポートされているわけではありません)、次を使用できます。

return System.Convert.ChangeType(
    enumValue,
    Enum.GetUnderlyingType(enumValue.GetType()));
12
Drew Noakes

ヘルパーメソッドを使用して車輪を再発明する必要があるのはなぜですか? enum値をその基になる型にキャストすることは完全に合法です。

タイピングが少なく、私の意見では読みやすいです...

int x = (int)DayOfWeek.Tuesday;

...のようなものではなく...

int y = Converter.ToInteger(DayOfWeek.Tuesday);
// or
int z = DayOfWeek.Tuesday.ToInteger();
10
LukeH

私の答えから ここ

次のように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つは見苦しいです。最初のものはより読みやすいはずですが、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();
4
nawfal

System.Enumからintへは、私にとっては問題なく機能します( [〜#〜] msdn [〜#〜] にもあります)。おそらく、それはResharperのバグです。

1
jpoh

Enumはbyte、sbyte、short、ushort、int、uint、long、ulongに制限されているため、いくつかの仮定を行うことができます。

利用可能な最大のコンテナを使用することにより、変換中の例外を回避できます。残念ながら、使用するコンテナは明確ではありません。なぜなら、ulongは負の数に対しては爆発し、longはlong.MaxValueとulong.MaxValueの間の数に対しては爆発するからです。基本となるタイプに基づいて、これらの選択肢を切り替える必要があります。

もちろん、結果がintに収まらない場合の対処方法を決定する必要があります。キャストは大丈夫だと思いますが、まだいくつかの落とし穴があります。

  1. int(longおよびulong)よりも大きいフィールドスペースを持つ型に基づく列挙型の場合、いくつかの列挙型が同じ値に評価される可能性があります。
  2. int.MaxValueより大きい数値をキャストすると、チェックされた領域にいる場合に例外がスローされます。

これが私の提案です。この関数を公開する場所を決めるのは読者に任せます。ヘルパーまたは拡張機能として。

public int ToInt(Enum e)
{
  unchecked
  {
    if (e.GetTypeCode() == TypeCode.UInt64)
      return (int)Convert.ToUInt64(e);
    else
      return (int)Convert.ToInt64(e);
  }
}
1
eisenpony