3626

C#でどのようintにキャストできますか?enum

4

32 に答える 32

4346

int から:

YourEnum foo = (YourEnum)yourInt;

文字列から:

YourEnum foo = (YourEnum) Enum.Parse(typeof(YourEnum), yourString);

// The foo.ToString().Contains(",") check is necessary for enumerations marked with an [Flags] attribute
if (!Enum.IsDefined(typeof(YourEnum), foo) && !foo.ToString().Contains(","))
{
    throw new InvalidOperationException($"{yourString} is not an underlying value of the YourEnum enumeration.")
}

アップデート:

番号からもできます

YourEnum foo = (YourEnum)Enum.ToObject(typeof(YourEnum) , yourInt);
于 2008-08-27T03:59:42.483 に答える
1038

キャストするだけです:

MyEnum e = (MyEnum)3;

Enum.IsDefinedを使用して範囲内にあるかどうかを確認できます。

if (Enum.IsDefined(typeof(MyEnum), 3)) { ... }
于 2008-08-27T04:01:14.600 に答える
265

または、ワンライナーの代わりに拡張メソッドを使用します。

public static T ToEnum<T>(this string enumString)
{
    return (T) Enum.Parse(typeof (T), enumString);
}

使用法:

Color colorEnum = "Red".ToEnum<Color>();

また

string color = "Red";
var colorEnum = color.ToEnum<Color>();
于 2011-11-11T13:27:35.430 に答える
197

完全な答えを得るには、列挙型が .NET の内部でどのように機能するかを知る必要があると思います。

仕組み

.NET の列挙型は、一連の値 (フィールド) を基本型 (デフォルトはint) にマップする構造です。ただし、実際には、列挙型がマップする整数型を選択できます。

public enum Foo : short

この場合、列挙型はshortデータ型にマップされます。つまり、列挙型は short としてメモリに格納され、キャストして使用すると short として動作します。

IL の観点から見ると、(通常の int) 列挙型は次のようになります。

.class public auto ansi serializable sealed BarFlag extends System.Enum
{
    .custom instance void System.FlagsAttribute::.ctor()
    .custom instance void ComVisibleAttribute::.ctor(bool) = { bool(true) }

    .field public static literal valuetype BarFlag AllFlags = int32(0x3fff)
    .field public static literal valuetype BarFlag Foo1 = int32(1)
    .field public static literal valuetype BarFlag Foo2 = int32(0x2000)

    // and so on for all flags or enum values

    .field public specialname rtspecialname int32 value__
}

ここで注目すべきは、value__が列挙値とは別に保存されていることです。上記の列挙Foo型の場合、型value__は int16 です。これは基本的に、型が一致する限り、列挙型に何でも格納できることを意味します。

System.Enumこの時点で、これが値型であることを指摘したいと思います。これは基本的BarFlagに、メモリ内で 4 バイトを使用し、Foo2 を使用することを意味します。たとえば、基になる型のサイズです (実際にはそれよりも複雑ですが、おい...)。

答え

したがって、列挙型にマップしたい整数がある場合、ランタイムは 2 つのことだけを行う必要があります。4 バイトをコピーして、別の名前 (列挙型の名前) を付けます。データは値型として保存されるため、コピーは暗黙的です。これは基本的に、アンマネージ コードを使用する場合、データをコピーせずに単に列挙型と整数を交換できることを意味します。

安全にするために、基になる型が同じか暗黙的に変換可能であることを確認し、列挙型の値が存在することを確認するのがベスト プラクティスだと思います(既定ではチェックされません!)。

これがどのように機能するかを確認するには、次のコードを試してください。

public enum MyEnum : int
{
    Foo = 1,
    Bar = 2,
    Mek = 5
}

static void Main(string[] args)
{
    var e1 = (MyEnum)5;
    var e2 = (MyEnum)6;

    Console.WriteLine("{0} {1}", e1, e2);
    Console.ReadLine();
}

へのキャストe2も機能することに注意してください。上記のコンパイラの観点から、これは理にかなっています。value__フィールドは単純に 5 または 6 で埋められ、 をConsole.WriteLine呼び出すとToString()、 の名前e1は解決されますが、 の名前は解決されe2ません。

Enum.IsDefined(typeof(MyEnum), 6)それが意図したものではない場合は、キャストしている値が定義済みの列挙型にマップされているかどうかを確認するために使用します。

また、コンパイラが実際にこれをチェックしているにもかかわらず、列挙型の基になる型について明示していることにも注意してください。これは、途中で予期せぬ事態に遭遇しないようにするためです。これらの驚きの動作を確認するには、次のコードを使用できます (実際、データベース コードでこれが頻繁に発生するのを見てきました)。

public enum MyEnum : short
{
    Mek = 5
}

static void Main(string[] args)
{
    var e1 = (MyEnum)32769; // will not compile, out of bounds for a short

    object o = 5;
    var e2 = (MyEnum)o;     // will throw at runtime, because o is of type int

    Console.WriteLine("{0} {1}", e1, e2);
    Console.ReadLine();
}
于 2014-04-03T07:39:44.587 に答える
133

次の例を見てください。

int one = 1;
MyEnum e = (MyEnum)one;
于 2008-08-27T04:00:38.877 に答える
72

このコードを使用して、int を列挙型にキャストしています。

if (typeof(YourEnum).IsEnumDefined(valueToCast)) return (YourEnum)valueToCast;
else { //handle it here, if its not defined }

私はそれが最善の解決策だと思います。

于 2011-10-21T10:05:43.790 に答える
62

以下は列挙型の便利なユーティリティ クラスです。

public static class EnumHelper
{
    public static int[] ToIntArray<T>(T[] value)
    {
        int[] result = new int[value.Length];
        for (int i = 0; i < value.Length; i++)
            result[i] = Convert.ToInt32(value[i]);
        return result;
    }

    public static T[] FromIntArray<T>(int[] value) 
    {
        T[] result = new T[value.Length];
        for (int i = 0; i < value.Length; i++)
            result[i] = (T)Enum.ToObject(typeof(T),value[i]);
        return result;
    }


    internal static T Parse<T>(string value, T defaultValue)
    {
        if (Enum.IsDefined(typeof(T), value))
            return (T) Enum.Parse(typeof (T), value);

        int num;
        if(int.TryParse(value,out num))
        {
            if (Enum.IsDefined(typeof(T), num))
                return (T)Enum.ToObject(typeof(T), num);
        }

        return defaultValue;
    }
}
于 2010-09-07T04:42:51.243 に答える
50

数値の場合、何があってもオブジェクトを返すため、これはより安全です。

public static class EnumEx
{
    static public bool TryConvert<T>(int value, out T result)
    {
        result = default(T);
        bool success = Enum.IsDefined(typeof(T), value);
        if (success)
        {
            result = (T)Enum.ToObject(typeof(T), value);
        }
        return success;
    }
}
于 2013-02-21T15:22:07.467 に答える
49

4.0 .NET Frameworkの準備ができている場合は、非常に便利で [Flags] 属性とうまく連携する新しいEnum.TryParse()関数があります。Enum.TryParse メソッド (文字列、TEnum%)を参照してください。

于 2011-11-01T14:58:49.043 に答える
41

型にオブジェクトがある場合がありますMyEnum。お気に入り

var MyEnumType = typeof(MyEnum);

それで:

Enum.ToObject(typeof(MyEnum), 3)
于 2010-07-02T14:41:41.690 に答える
40

ビットマスクとして機能し、[Flags]列挙で1つ以上の値を表すことができる整数がある場合は、このコードを使用して、個々のフラグ値をリストに解析できます。

for (var flagIterator = 0; flagIterator < 32; flagIterator++)
{
    // Determine the bit value (1,2,4,...,Int32.MinValue)
    int bitValue = 1 << flagIterator;

    // Check to see if the current flag exists in the bit mask
    if ((intValue & bitValue) != 0)
    {
        // If the current flag exists in the enumeration, then we can add that value to the list
        // if the enumeration has that flag defined
        if (Enum.IsDefined(typeof(MyEnum), bitValue))
            Console.WriteLine((MyEnum)bitValue);
    }
}

enumこれは、の基になる型が符号付き32ビット整数であることを前提としていることに注意してください。別の数値タイプの場合は、ハードコードされた32を変更して、そのタイプのビットを反映する必要があります(または、を使用してプログラムで導出する必要がありますEnum.GetUnderlyingType()) 。

于 2011-04-13T20:13:13.577 に答える
30

これは、フラグ列挙型の安全な変換メソッドです。

public static bool TryConvertToEnum<T>(this int instance, out T result)
  where T: Enum
{
  var enumType = typeof (T);
  var success = Enum.IsDefined(enumType, instance);
  if (success)
  {
    result = (T)Enum.ToObject(enumType, instance);
  }
  else
  {
    result = default(T);
  }
  return success;
}
于 2015-03-30T10:08:03.833 に答える
22

ここに画像の説明を入力

文字列を ENUM に、または int を ENUM 定数に変換するには、Enum.Parse 関数を使用する必要があります。これは実際に文字列を使用したデモを行うYouTubeビデオhttps://www.youtube.com/watch?v=4nhx4VwdRDk であり、同じことがintにも当てはまります。

コードは次のようになります。ここで、「red」は文字列で、「MyColors」は色定数を持つ色 ENUM です。

MyColors EnumColors = (MyColors)Enum.Parse(typeof(MyColors), "Red");
于 2014-02-05T12:15:25.420 に答える
19

以下は、わずかに優れた拡張方法です。

public static string ToEnumString<TEnum>(this int enumValue)
{
    var enumString = enumValue.ToString();
    if (Enum.IsDefined(typeof(TEnum), enumValue))
    {
        enumString = ((TEnum) Enum.ToObject(typeof (TEnum), enumValue)).ToString();
    }
    return enumString;
}
于 2016-12-16T06:59:17.917 に答える
18

これは、 Tawani のユーティリティ クラスのようなジェネリックを使用して、.NET 4.0 の部分一致で整数または文字列をターゲット列挙型に解析します。不完全なコマンドラインスイッチ変数を変換するために使用しています。列挙型を null にすることはできないため、デフォルト値を論理的に指定する必要があります。次のように呼び出すことができます。

var result = EnumParser<MyEnum>.Parse(valueToParse, MyEnum.FirstValue);

コードは次のとおりです。

using System;

public class EnumParser<T> where T : struct
{
    public static T Parse(int toParse, T defaultVal)
    {
        return Parse(toParse + "", defaultVal);
    }
    public static T Parse(string toParse, T defaultVal)
    {
        T enumVal = defaultVal;
        if (defaultVal is Enum && !String.IsNullOrEmpty(toParse))
        {
            int index;
            if (int.TryParse(toParse, out index))
            {
                Enum.TryParse(index + "", out enumVal);
            }
            else
            {
                if (!Enum.TryParse<T>(toParse + "", true, out enumVal))
                {
                    MatchPartialName(toParse, ref enumVal);
                }
            }
        }
        return enumVal;
    }

    public static void MatchPartialName(string toParse, ref T enumVal)
    {
        foreach (string member in enumVal.GetType().GetEnumNames())
        {
            if (member.ToLower().Contains(toParse.ToLower()))
            {
                if (Enum.TryParse<T>(member + "", out enumVal))
                {
                    break;
                }
            }
        }
    }
}

参考までに: 質問は整数に関するもので、誰も言及していませんが、Enum.TryParse()でも明示的に変換されます

于 2014-07-30T20:02:52.630 に答える
11

Int32にキャストする拡張メソッドを次に示しEnumます。

値が可能な最大値よりも高い場合でも、ビットごとのフラグを尊重します。たとえば、可能性が12、および4の列挙型があるが、int が9である場合、8がない場合は1として理解されます。これにより、コードを更新する前にデータを更新できます。

   public static TEnum ToEnum<TEnum>(this int val) where TEnum : struct, IComparable, IFormattable, IConvertible
    {
        if (!typeof(TEnum).IsEnum)
        {
            return default(TEnum);
        }

        if (Enum.IsDefined(typeof(TEnum), val))
        {//if a straightforward single value, return that
            return (TEnum)Enum.ToObject(typeof(TEnum), val);
        }

        var candidates = Enum
            .GetValues(typeof(TEnum))
            .Cast<int>()
            .ToList();

        var isBitwise = candidates
            .Select((n, i) => {
                if (i < 2) return n == 0 || n == 1;
                return n / 2 == candidates[i - 1];
            })
            .All(y => y);

        var maxPossible = candidates.Sum();

        if (
            Enum.TryParse(val.ToString(), out TEnum asEnum)
            && (val <= maxPossible || !isBitwise)
        ){//if it can be parsed as a bitwise enum with multiple flags,
          //or is not bitwise, return the result of TryParse
            return asEnum;
        }

        //If the value is higher than all possible combinations,
        //remove the high imaginary values not accounted for in the enum
        var excess = Enumerable
            .Range(0, 32)
            .Select(n => (int)Math.Pow(2, n))
            .Where(n => n <= val && n > 0 && !candidates.Contains(n))
            .Sum();

        return Enum.TryParse((val - excess).ToString(), out asEnum) ? asEnum : default(TEnum);
    }
于 2019-02-22T01:31:39.700 に答える
10

入力データをユーザーが希望するenumに変換するのに役立ちます。以下のような列挙型があり、デフォルトでintがあるとします。列挙型の最初にデフォルト値を追加してください。入力値との一致が見つからない場合にヘルパー メソッドで使用されます。

public enum FriendType  
{
    Default,
    Audio,
    Video,
    Image
}

public static class EnumHelper<T>
{
    public static T ConvertToEnum(dynamic value)
    {
        var result = default(T);
        var tempType = 0;

        //see Note below
        if (value != null &&
            int.TryParse(value.ToString(), out  tempType) && 
            Enum.IsDefined(typeof(T), tempType))
        {
            result = (T)Enum.ToObject(typeof(T), tempType); 
        }
        return result;
    }
}

NB:ここでは、値を int に解析しようとします。これは、enum がデフォルトでintであるためです。バイト型 であるこのように enum を定義する場合。

public enum MediaType : byte
{
    Default,
    Audio,
    Video,
    Image
} 

ヘルパーメソッドでの解析をから変更する必要があります

int.TryParse(value.ToString(), out  tempType)

byte.TryParse(value.ToString(), out tempType)

次の入力の方法を確認します

EnumHelper<FriendType>.ConvertToEnum(null);
EnumHelper<FriendType>.ConvertToEnum("");
EnumHelper<FriendType>.ConvertToEnum("-1");
EnumHelper<FriendType>.ConvertToEnum("6");
EnumHelper<FriendType>.ConvertToEnum("");
EnumHelper<FriendType>.ConvertToEnum("2");
EnumHelper<FriendType>.ConvertToEnum(-1);
EnumHelper<FriendType>.ConvertToEnum(0);
EnumHelper<FriendType>.ConvertToEnum(1);
EnumHelper<FriendType>.ConvertToEnum(9);

私の英語でごめんなさい

于 2016-11-17T12:49:05.530 に答える
9

キャストするさまざまな方法 Enum

enum orientation : byte
{
 north = 1,
 south = 2,
 east = 3,
 west = 4
}

class Program
{
  static void Main(string[] args)
  {
    orientation myDirection = orientation.north;
    Console.WriteLine(“myDirection = {0}”, myDirection); //output myDirection =north
    Console.WriteLine((byte)myDirection); //output 1

    string strDir = Convert.ToString(myDirection);
        Console.WriteLine(strDir); //output north

    string myString = “north”; //to convert string to Enum
    myDirection = (orientation)Enum.Parse(typeof(orientation),myString);


 }
}
于 2014-01-08T15:18:34.203 に答える
6

以下のようにするだけです:

int intToCast = 1;
TargetEnum f = (TargetEnum) intToCast ;

正しい値のみをキャストし、それ以外の場合は例外をスローできることを確認するには:

int intToCast = 1;
if (Enum.IsDefined(typeof(TargetEnum), intToCast ))
{
    TargetEnum target = (TargetEnum)intToCast ;
}
else
{
   // Throw your exception.
}

IsDefined の使用はコストがかかり、キャストするだけではないことに注意してください。そのため、使用するかどうかは実装に依存します。

于 2019-07-27T07:48:20.697 に答える
6

シンプルに int を列挙型にキャストできます

 public enum DaysOfWeeks
    {
        Monday = 1,
        Tuesday = 2,
        Wednesday = 3,
        Thursday = 4,
        Friday = 5,
        Saturday = 6,
        Sunday = 7,
    } 

    var day= (DaysOfWeeks)5;
    Console.WriteLine("Day is : {0}", day);
    Console.ReadLine();
于 2020-06-10T05:19:51.487 に答える