提问



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


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


Questions类中,我有get(int foo)函数,为foo返回Questions对象。有没有一种简单的方法从枚举中获取整数值,所以我可以做Questions.Get(Question.Role)之类的东西?

最佳参考


刚刚施放枚举,例如


int something = (int) Question.Role;


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


但是,正如cecilphillip所指出的,枚举可以有不同的底层类型。
如果枚举声明为uintlongulong,则应将其强制转换为枚举的类型;例如对于


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


你应该使用


long something = (long)StarsInMilkyWay.Wolf424B;

其它参考1


由于Enums可以是任何整数类型(byteintshort等,因此获得枚举的基础整数值的更健壮的方法是利用GetTypeCode方法与Convert类一起使用:


enum Sides {
    Left, Right, Top, Bottom
}
Sides side = Sides.Bottom;

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


无论底层整数类型如何,这都应该有效。

其它参考2


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


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或你定义的任何东西。

其它参考3


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


将导致value == 2

其它参考4


在相关的说明中,如果要从System.Enum获取int值,则在此处给出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);


最后两个是丑陋的。我更喜欢第一个。

其它参考5


它比你想象的容易 - 枚举已经是一个整数。它只需要提醒:


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

其它参考6


例:


Public Enum EmpNo
{
    Raj = 1
    Rahul,
    Priyanka
}


并在后面的代码中获取枚举值:


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


要么


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


枚举将增加1,您可以设置起始值。否则它最初将被指定为0。

其它参考7


我最近在代码中转而使用枚举,转而使用带有受保护构造函数和预定义静态实例的类(感谢Roelof - C#确保有效枚举值 - Futureproof方法)。


鉴于此,下面的我如何现在解决这个问题(包括隐式转换为/int)。


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


这种方法的优点是你可以从枚举中获得所有内容,但是你的代码现在更加灵活,所以如果你需要根据Question的值执行不同的操作,你可以将逻辑放入Question本身(即以首选的OO方式),而不是在整个代码中放置大量的case语句来处理每个场景。





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

其它参考8


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


// 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() + ".");


我希望这有帮助。

其它参考9


如果你想得到存储在变量中的枚举值的整数,其类型是Question,例如在方法中使用,你可以简单地这样做我在这个例子中写的:


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。


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

其它参考10


还有一种方法:


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


将导致:


Name: Role, Value: 2

其它参考11


也许我错过了它,但有人试过一个简单的通用扩展方法。这对我很有用。您可以通过这种方式避免API中的类型转换,但最终会导致更改类型操作。这是编程Roselyn以使编译器为您创建GetValue方法的好例子。


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

其它参考12


您可以通过对定义的枚举类型实施扩展方法来实现此目的:


public static class MyExtensions
{
    public static int getNumberValue(this Question questionThis)
    {
        return (int)questionThis;
    }
}


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


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


要么


int value = Question.Role.getNumberValue();

其它参考13


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


......是一个很好的宣言。


你必须像这样将结果转换为int:


int Question = (int)QuestionType.Role


否则,类型仍然是QuestionType


这种严格程度是C#方式。


一种替代方法是使用类声明:


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
}


声明它不太优雅,但你不需要在代码中强制转换它:


int Question = QuestionType.Role


或者,您可能会对Visual Basic感到更舒服,因为Visual Basic可以满足许多领域的这种期望。

其它参考14


如何改为扩展方法:


public static class ExtensionMethods
{
    public static int IntValue(this Enum argEnum)
    {
        return Convert.ToInt32(argEnum);
    }
}


而且用法稍微漂亮一些:


var intValue = Question.Role.IntValue();

其它参考15


int number = Question.Role.GetHashCode();


number应该具有值2

其它参考16


我能想到的最简单的解决方案是重载Get(int)方法,如下所示:


[modifiers] Questions Get(Question q)
{
    return Get((int)q);
}


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


public static class Extensions
{
    public static Questions Get(this Questions qs, Question q)
    {
        return qs.Get((int)q);
    }
}

其它参考17


以下是扩展方法


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

其它参考18


尝试这个而不是将枚举转换为int:


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

其它参考19


我最喜欢使用int或更小的枚举:


GetHashCode();


对于一个枚举


public enum Test
{
    Min = Int32.MinValue,
    One = 1,
    Max = Int32.MaxValue,
}


这个


var values = Enum.GetValues(typeof(Test));

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


输出


one
1
1  
max
2147483647
2147483647    
min
-2147483648
-2147483648    


声明:
基于长期不适用于枚举

其它参考20


我想建议从enum获取int值的例子是,


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

int answer = (int)Sample.Book;


现在的答案是1。


我希望这可能对某人有所帮助。

其它参考21


在Vb。它应该是


Public Enum Question
    Role = 2
    ProjectFunding = 3
    TotalEmployee = 4
    NumberOfServers = 5
    TopBusinessConcern = 6
End Enum

Private value As Integer = CInt(Question.Role)

其它参考22


由于可以使用多个基本类型声明枚举,因此用于转换任何枚举类型的通用扩展方法可能很有用。


        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;

其它参考23


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

其它参考24


尝试这个 :


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