C#中从enum获取int值

Get int value from enum in C#

我有一个叫Questions的班(复数)。在这个类中有一个名为Question的枚举(单数),它看起来像这样。

1
2
3
4
5
6
7
8
public enum Question
{
    Role = 2,
    ProjectFunding = 3,
    TotalEmployee = 4,
    NumberOfServers = 5,
    TopBusinessConcern = 6
}

Questions类中,我有一个get(int foo)函数,它为该foo返回一个Questions对象。是否有一种简单的方法从枚举中获取整数值,以便我可以执行类似于Questions.Get(Question.Role)的操作?


只需强制转换枚举,例如

1
int something = (int) Question.Role;

上面的内容适用于您在野外看到的绝大多数枚举,因为枚举的默认底层类型是int

然而,正如Cecilphillip指出的,枚举可以有不同的底层类型。如果枚举声明为uintlongulong类型,则应将其强制转换为枚举的类型;例如

1
enum StarsInMilkyWay:long {Sun = 1, V645Centauri = 2 .. Wolf424B = 2147483649};

你应该使用

1
long something = (long)StarsInMilkyWay.Wolf424B;


由于枚举可以是任何整数类型(byteintshort等),获得枚举的基本整数值的更可靠方法是将GetTypeCode方法与Convert类结合使用:

1
2
3
4
5
6
7
enum Sides {
    Left, Right, Top, Bottom
}
Sides side = Sides.Bottom;

object val = Convert.ChangeType(side, side.GetTypeCode());
Console.WriteLine(val);

不管底层的整型是什么,这都应该有效。


将其声明为具有公共常量的静态类:

1
2
3
4
5
6
7
8
public static class Question
{
    public const int Role = 2;
    public const int ProjectFunding = 3;
    public const int TotalEmployee = 4;
    public const int NumberOfServers = 5;
    public const int TopBusinessConcern = 6;
}

然后你可以引用它作为Question.Role,它总是计算为int或者你定义它的任何东西。


1
2
Question question = Question.Role;
int value = (int) question;

会导致value == 2


在相关注释中,如果您想从System.Enum中获得int值,那么在这里给出e

1
Enum e = Question.Role;

你可以使用:

1
2
3
4
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);

最后两个很难看。我喜欢第一个。


这比你想象的要简单-枚举已经是int了。只需要提醒一下:

1
2
int y = (int)Question.Role;
Console.WriteLine(y); // prints 2


例子:

1
2
3
4
5
6
public Enum EmpNo
{
    Raj = 1,
    Rahul,
    Priyanka
}

在代码后面获取枚举值:

1
int setempNo = (int)EmpNo.Raj; //This will give setempNo = 1

1
int setempNo = (int)EmpNo.Rahul; //This will give setempNo = 2

枚举将增加1,您可以设置起始值。如果不设置起始值,则最初会将其指定为0。


最近,我不再在代码中使用枚举,而是改用带有受保护的构造函数和预定义静态实例的类(这要归功于roelof-c确保有效的枚举值-futureProof方法)。

有鉴于此,下面是我现在处理这个问题的方法(包括隐式转换到/从int)。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
public class Question
{
    // Attributes
    protected int index;
    protected string name;
    // Go with a dictionary to enforce unique index
    //protected static readonly ICollection<Question> values = new Collection<Question>();
    protected static readonly IDictionary<int,Question> values = new Dictionary<int,Question>();

    // Define the"enum" values
    public static readonly Question Role = new Question(2,"Role");
    public static readonly Question ProjectFunding = new Question(3,"Project Funding");
    public static readonly Question TotalEmployee = new Question(4,"Total Employee");
    public static readonly Question NumberOfServers = new Question(5,"Number of Servers");
    public static readonly Question TopBusinessConcern = new Question(6,"Top Business Concern");

    // Constructors
    protected Question(int index, string name)
    {
        this.index = index;
        this.name = name;
        values.Add(index, this);
    }

    // Easy int conversion
    public static implicit operator int(Question question) =>
        question.index; //nb: if question is null this will return a null pointer exception

    public static implicit operator Question(int index) =>        
        values.TryGetValue(index, out var question) ? question : null;

    // Easy string conversion (also update ToString for the same effect)
    public override string ToString() =>
        this.name;

    public static implicit operator string(Question question) =>
        question?.ToString();

    public static implicit operator Question(string name) =>
        name == null ? null : values.Values.FirstOrDefault(item => name.Equals(item.name, StringComparison.CurrentCultureIgnoreCase));


    // If you specifically want a Get(int x) function (though not required given the implicit converstion)
    public Question Get(int foo) =>
        foo; //(implicit conversion will take care of the conversion for you)
}

这种方法的优点是,您可以从枚举中获得所需的一切,但是您的代码现在更加灵活,因此,如果您需要根据EDOCX1的值(10)执行不同的操作,那么您可以将逻辑放入Question本身(即以首选的OO方式),而不是将大量的case语句放在您的整个系统中。R代码处理每个场景。

注意:答案更新了2018-04-27,以利用C 6功能,即声明表达式和lambda表达式体定义。原始代码见修订历史。这样做的好处是让这个定义不那么冗长;这是关于这个答案方法的主要抱怨之一。


如果要为存储在变量中的枚举值获取一个整数,则类型为Question,例如在方法中使用,可以简单地执行我在本例中编写的操作:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
enum Talen
{
    Engels = 1, Italiaans = 2, Portugees = 3, Nederlands = 4, Duits = 5, Dens = 6
}

Talen Geselecteerd;    

public void Form1()
{
    InitializeComponent()
    Geselecteerd = Talen.Nederlands;
}

// You can use the Enum type as a parameter, so any enumeration from any enumerator can be used as parameter
void VeranderenTitel(Enum e)
{
    this.Text = Convert.ToInt32(e).ToString();
}

这会将窗口标题更改为4,因为变量GeselecteerdTalen.Nederlands。如果我把它改为Talen.Portugees并再次调用该方法,文本将改为3。

我很难在互联网上找到这个简单的解决方案,我找不到它,所以我在测试一些东西,然后发现了这个问题。希望这有帮助。;)


为了确保枚举值存在,然后分析它,您还可以执行以下操作。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// Fake Day of Week
string strDOWFake ="SuperDay";
// Real Day of Week
string strDOWReal ="Friday";
// Will hold which ever is the real DOW.
DayOfWeek enmDOW;

// See if fake DOW is defined in the DayOfWeek enumeration.
if (Enum.IsDefined(typeof(DayOfWeek), strDOWFake))
{
// This will never be reached since"SuperDay"
// doesn't exist in the DayOfWeek enumeration.
    enmDOW = (DayOfWeek)Enum.Parse(typeof(DayOfWeek), strDOWFake);
}
// See if real DOW is defined in the DayOfWeek enumeration.
else if (Enum.IsDefined(typeof(DayOfWeek), strDOWReal))
{
    // This will parse the string into it's corresponding DOW enum object.
    enmDOW = (DayOfWeek)Enum.Parse(typeof(DayOfWeek), strDOWReal);
}

// Can now use the DOW enum object.
Console.Write("Today is" + enmDOW.ToString() +".");

我希望这有帮助。


也许我错过了,但有人尝试过一个简单的通用扩展方法吗?这对我很有用。这样可以避免API中的类型转换,但最终会导致更改类型操作。对于编程Roselyn来说,让编译器为您生成getValue方法是一个很好的例子。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
    public static void Main()
    {
        int test = MyCSharpWrapperMethod(TestEnum.Test1);

        Debug.Assert(test == 1);
    }

    public static int MyCSharpWrapperMethod(TestEnum customFlag)
    {
        return MyCPlusPlusMethod(customFlag.GetValue<int>());
    }

    public static int MyCPlusPlusMethod(int customFlag)
    {
        //Pretend you made a PInvoke or COM+ call to C++ method that require an integer
        return customFlag;
    }

    public enum TestEnum
    {
        Test1 = 1,
        Test2 = 2,
        Test3 = 3
    }
}

public static class EnumExtensions
{
    public static T GetValue<T>(this Enum enumeration)
    {
        T result = default(T);

        try
        {
            result = (T)Convert.ChangeType(enumeration, typeof(T));
        }
        catch (Exception ex)
        {
            Debug.Assert(false);
            Debug.WriteLine(ex);
        }

        return result;
    }
}


另一种方法是:

1
Console.WriteLine("Name: {0}, Value: {0:D}", Question.Role);

将导致:

1
Name: Role, Value: 2

1
2
3
4
5
6
7
8
public enum QuestionType
{
    Role = 2,
    ProjectFunding = 3,
    TotalEmployee = 4,
    NumberOfServers = 5,
    TopBusinessConcern = 6
}

…是一个很好的声明。

您必须将结果强制转换为int,如下所示:

1
int Question = (int)QuestionType.Role

否则,类型仍然是QuestionType

这种严格程度是C方式。

另一种选择是改用类声明:

1
2
3
4
5
6
7
8
public class QuestionType
{
    public static int Role = 2,
    public static int ProjectFunding = 3,
    public static int TotalEmployee = 4,
    public static int NumberOfServers = 5,
    public static int TopBusinessConcern = 6
}

声明不太优雅,但您不需要将其强制转换为代码:

1
int Question = QuestionType.Role

或者,您可能会对VisualBasic感到更舒服,它在许多领域都能满足这种期望。


1
int number = Question.Role.GetHashCode();

number的值应该是2的值。


可以通过对定义的枚举类型实现扩展方法来完成此操作:

1
2
3
4
5
6
7
public static class MyExtensions
{
    public static int getNumberValue(this Question questionThis)
    {
        return (int)questionThis;
    }
}

这简化了获取当前枚举值的int值:

1
2
Question question = Question.Role;
int value = question.getNumberValue();

1
int value = Question.Role.getNumberValue();


改为扩展方法如何:

1
2
3
4
5
6
7
public static class ExtensionMethods
{
    public static int IntValue(this Enum argEnum)
    {
        return Convert.ToInt32(argEnum);
    }
}

而且使用起来稍微漂亮一点:

1
var intValue = Question.Role.IntValue();

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
public enum Suit : int
{
    Spades = 0,
    Hearts = 1,
    Clubs = 2,
    Diamonds = 3
}

Console.WriteLine((int)(Suit)Enum.Parse(typeof(Suit),"Clubs"));

//from int
Console.WriteLine((Suit)1);

//From number you can also
Console.WriteLine((Suit)Enum.ToObject(typeof(Suit), 1));

if (typeof(Suit).IsEnumDefined("Spades"))
{
    var res = (int)(Suit)Enum.Parse(typeof(Suit),"Spades");
    Console.Out.WriteLine("{0}", res);
}

我的fav-hack使用int或更小的枚举:

1
GetHashCode();

为枚举

1
2
3
4
5
6
public enum Test
{
    Min = Int32.MinValue,
    One = 1,
    Max = Int32.MaxValue,
}

1
2
3
4
5
6
7
8
var values = Enum.GetValues(typeof(Test));

foreach (var val in values)
{
    Console.WriteLine(val.GetHashCode());
    Console.WriteLine(((int)val));
    Console.WriteLine(val);
}

输出

1
2
3
4
5
6
7
8
9
one
1
1  
max
2147483647
2147483647    
min
-2147483648
-2147483648

免责声明:不适用于基于long的枚举


下面是扩展方法

1
2
3
4
5
6
7
8
9
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;
}


由于枚举可以用多个基元类型声明,因此可以使用通用扩展方法来强制转换任何枚举类型。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
enum Box
{
    HEIGHT,
    WIDTH,
    DEPTH
}

public static void UseEnum()
{
    int height = Box.HEIGHT.GetEnumValue<int>();
    int width = Box.WIDTH.GetEnumValue<int>();
    int depth = Box.DEPTH.GetEnumValue<int>();
}

public static T GetEnumValue<T>(this object e) => (T)e;

我建议"从枚举中获取"int"值的示例是,"

1
2
3
4
public enum Sample
{Book =1, Pen=2, Pencil =3}

int answer = (int)Sample.Book;

现在答案是1。

我希望这能帮助别人。


尝试此方法,而不是将枚举转换为int:

1
2
3
4
5
6
public static class ReturnType
{
    public static readonly int Success = 1;
    public static readonly int Duplicate = 2;
    public static readonly int Error = -1;        
}

在VB中。应该是

1
2
3
4
5
6
7
8
9
Public Enum Question
    Role = 2
    ProjectFunding = 3
    TotalEmployee = 4
    NumberOfServers = 5
    TopBusinessConcern = 6
End Enum

Private value As Integer = CInt(Question.Role)


我能想到的最简单的解决方案是重载这样的Get(int)方法:

1
2
3
4
[modifiers] Questions Get(Question q)
{
    return Get((int)q);
}

其中,[modifiers]一般与Get(int)方法相同。如果不能编辑Questions类,或者由于某种原因不想编辑,可以通过编写扩展来重载方法:

1
2
3
4
5
6
7
public static class Extensions
{
    public static Questions Get(this Questions qs, Question q)
    {
        return qs.Get((int)q);
    }
}


我有点晚了,但我想出了包括当前语言功能的扩展方法。通过使用dynamic,我不需要将其设置为泛型方法,并指定保持调用简单和一致的类型。如果我做错了请告诉我:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
public static class EnumEx
{
    public static dynamic Value(this Enum e)
    {
        switch (e.GetTypeCode())
        {
        case TypeCode.Byte:
            {
                return (byte) (IConvertible) e;
            }
        case TypeCode.Int16:
            {
                return (short) (IConvertible) e;
            }
        case TypeCode.Int32:
            {
                return (int) (IConvertible) e;
            }
        case TypeCode.Int64:
            {
                return (long) (IConvertible) e;
            }
        case TypeCode.UInt16:
            {
                return (ushort) (IConvertible) e;
            }
        case TypeCode.UInt32:
            {
                return (uint) (IConvertible) e;
            }
        case TypeCode.UInt64:
            {
                return (ulong) (IConvertible) e;
            }
        case TypeCode.SByte:
            {
                return (sbyte) (IConvertible) e;
            }
        }

        return 0;
    }

试试这个:

1
int value = YourEnum.ToString("D");