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

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


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

评论

另外一种方法是:将int枚举到c-sharp中。

我知道我迟到了,但是除了将您的方法定义为get(int foo)之外,您可以将其定义为get(Question foo)然后在方法内部进行转换,您可以将您的方法称为Questions.Get (Question.Role)

#1 楼

只需转换枚举,例如

int something = (int) Question.Role;


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

但是,正如cecilphillip指出的那样,枚举可以具有不同的基础类型。
如果将枚举声明为uintlongulong,则应将其强制转换为枚举的类型。 ;例如for

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


您应该使用

long something = (long)StarsInMilkyWay.Wolf424B;


评论


@哈里这不是真的。您可以创建不枚举的枚举,这不是必需的。并且我只在特殊情况下分配编号,在大多数情况下,我将其保留为默认值。但是您可以进行枚举Test {Item = 1}并看到1 ==(int)Test.Item相等。

–贾德
2012年6月28日在20:47

@Jaider(int)Test.Item那是演员! ()是显式强制转换运算符。

–辛西娅五世
2012年7月26日19:02

@Sinthia V他说您可以不进行铸造就创建它,这是正确的

– Paul Ridgway
2012年8月17日在18:30

如果enum Question的基础类型不是int而是long,则此强制转换将截断Roles的整数值!

– quaylar
13-10-29在16:14

当您接受Enum作为参数时,您知道只能获得固定数量的可能的整数值。另一方面,如果仅采用一个int,则必须验证该int是否在可接受的值之内,从而使代码复杂化。您始终可以覆盖签名,例如```public void MyMethod(int x){//用x做某事} public void MyMethod(Enum x){this.MyMethod((int)x); }````

–percebus
15年8月18日在16:52

#2 楼

由于Enums可以是任何整数类型(byteintshort等),因此获取枚举的基础整数值的更可靠的方法是结合使用GetTypeCode方法和Convert类: >
enum Sides {
    Left, Right, Top, Bottom
}
Sides side = Sides.Bottom;

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


无论底层整数类型如何,此方法都应起作用。

评论


在处理T:enum(实际上是T:struct,IConvertible,但这是另一回事)的泛型类型时,这项技术对我来说是值得的。

– aboy021
2011年7月5日在23:20

您将如何修改它以打印出side的十六进制值?本示例显示了十进制值。问题在于var是object类型,因此您需要将其拆箱,并且它变得比我想要的更混乱。

–马克·拉卡塔(Mark Lakata)
2012年11月9日,2:15

如果要转换为int,请尝试(在枚举Sides:int的情况下)[...]对象val = Convert.ChangeType(side,typeof(int)); [...]

–theLaw
2014年6月9日在16:05



@TimAbell我真正能说的是,我们发现动态编译的aspx页(您必须在其中将.cs文件部署到活动服务器中)将整数分配给每个值。这意味着一台机器上的序列化对象在另一台机器上以不同的值进行反序列化,并有效地被破坏(造成数小时的混乱)。我们用MS提出的,我似乎还记得他们说过,跨不同框架版本构建时,不能保证自动生成的整数是相同的。

– NickG
15年3月24日在9:42

@TimAbell在另一个情况下,开发人员删除了一个过时的/未使用的Enum值,导致序列中的所有其他值都被减一。因此,我们的编码标准现在要求始终明确指定ID,否则添加/删除甚至自动格式化代码(例如,按字母顺序排序)将更改所有值,从而导致数据损坏。我强烈建议任何人明确指定所有Enum整数。如果它们与外部(数据库)存储的值相关联,则这非常重要。

– NickG
15年3月24日在9:46

#3 楼

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

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或您定义的任何内容。

评论


我将使用静态只读int,因为常量已编译为它们的硬值。见stackoverflow.com/a/755693/492

– CAD bloke
13年5月15日在23:16

该解决方案实际上并未提供强类型枚举的真正好处。例如,如果我只想将GameState-enum-parameter传递给特定方法,则编译器不应允许我将任何int变量作为参数传递。

– thgc
2014年4月12日在18:24

@CADBloke正是为什么要使用const而不是static readonly的原因,因为每次比较静态readonly时,您都在进行方法调用以获取变量的值,而使用const时,您将直接比较两种值类型。

– Blockloop
14年8月14日在17:11

@ brettof86是的,一个const会更快,如果编译限制永远不会成为问题,那么一切都很好。

– CAD bloke
2014年8月15日上午10:57

@Zack我没有很好地解释这一点,由于编译限制,我的意思是该值在编译时会进行硬编码,因此对该值的任何更改都将需要重新编译使用该值的所有程序集。对于用法,我倾向于同意您的意见,因为更改值将产生深远的影响。

– CAD bloke
15年4月22日在21:53

#4 楼

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


将产生value == 2

评论


像这样的问题Questions.Get(Convert.ToInt16(Question.Applications))

– Jim
09年3月3日,下午6:51

您可以向任一方向简单投射;唯一需要注意的是枚举不执行任何操作(枚举值可以是288,即使该数字不存在任何问题)

– Marc Gravell♦
09年3月3日在6:54

@jim:不,只需将值强制转换为:Questions.Get((int)Question.Applications);

–古法
09年3月3日在6:55

#5 楼

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


最后两个很丑陋。我喜欢第一个。

评论


第二个是最快的。

– Johan B
19年6月16日在11:47

作为习惯在Minecraft改装中使用Mixins的人,第二个似乎是显而易见的赢家。

–社会
19-10-14在7:46

第五个选项(如大多数答案所说)是:int i =(int)e; (不先投射对象)

– andreyk2 Hohlov
8月17日9:06



@ andreyk2Hohlov无法将类型'System.Enum'转换为'int'

– nawfal
8月18日9:48

#6 楼

比您想象的要容易-枚举已经是一个int。只需提醒一下:

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


评论


Nitpick:此枚举已经是一个int。其他枚举可能是不同的类型-尝试“枚举SmallEnum:字节{A,B,C}”

–mqp
09年6月3日,6:56

绝对真实。 C#参考:“每个枚举类型都有一个基础类型,可以是除char之外的任何整数类型。”

–迈克尔·彼得罗塔(Michael Petrotta)
09年6月3日在6:59

#7 楼

示例:
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。

评论


拉杰(Rajul)或普里扬卡(Priyanka)可以是拉吉(Rahul)还是普里扬卡(Priyanka)?您的价值观存在冲突,因此应该加倍体现出独特性,例如0、1、2、4、8等。这是我对枚举的核心关注。

–提莫西·冈萨雷斯(Timothy Gonzalez)
16年11月14日在21:58

如果您未明确指定@TimothyGonzalez的值,它实际上只是简单地将其枚举1;)

– derHugo
19-10-10在22:30

@derHugo,这取决于您假设数值是以10为底还是以2为底。

–提莫西·冈萨雷斯(Timothy Gonzalez)
19-10-11在14:57

@TimothyGonzalez没什么好假设的。。。我只是指出默认情况下,它们只在int上加1,除非您明确定义否则

– derHugo
19-10-11在14:59

#8 楼

最近,我不再使用代码中的枚举,而是改为使用具有受保护的构造函数和预定义的静态实例的类(由于Roelof-C#确保有效的枚举值-Futureproof方法)。

这样,下面就是我现在如何处理此问题(包括隐式转换到int或从Question隐式转换)。从枚举开始,但是您的代码现在更加灵活,因此如果您需要基于Question的值执行不同的操作,则可以将逻辑放入q4312079q本身(即以首选的OO方式),而不是放置大量的case语句NB:请回答2018年6月27日更新,以利用C#6功能;即声明表达式和lambda表达式主体定义。有关原始代码,请参见修订历史记录。这样做的好处是使定义不再那么冗长。这是对该答案方法的主要抱怨之一。

评论


我想这是在显式强制转换和必须编写的代码之间进行权衡的方法。仍然喜欢该实现,只是希望它没有那么长。 +1

– Lankymart
13年8月2日在10:40

我使用了几种不同类型的类,其结构与此类似。我发现他们在尝试遵循“以后不要让我成为白痴”方法时产生了奇迹。

–詹姆斯·豪格(James Haug)
16年8月8日在16:13

#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。

评论


不幸的是,这种方法使用得越多,性能就会越差。我用我的一些代码尝试了一下,随着时间的流逝,我的应用程序越来越慢,CPU使用率也越来越少。这意味着线程正在等待某些东西-我假设某种垃圾回收,可能是由于将Toumt32()的枚举参数装箱了。通过切换到简单的int.Parse(),我可以完全消除这种不良的性能,并且无论代码运行多长时间,性能都保持不变。

–格雷格
19年2月4日在18:38

#10 楼

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

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


#11 楼

另一种方法是:

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


结果将是:

Name: Role, Value: 2


评论


这是我的用例的最佳解决方案,因为我的枚举是int和long值的混合体

–安迪
10月28日17:35

#12 楼

也许我错过了,但是有人尝试过一种简单的通用扩展方法吗?

对我来说很棒。您可以通过这种方式避免在API中进行类型转换,但最终会导致更改类型操作。这是对Roslyn进行编程以使编译器为您创建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;
    }
}


评论


可能是因为执行(int)customFlag较少在各处键入内容,或多或少是同一件事?

–蒂姆·基廷(Tim Keating)
2014年11月11日17:32

关于“也许我错过了,但是有人尝试过一种简单的通用扩展方法吗?”:SixOThree说“改为使用扩展方法”,而Bronek说“可以通过对定义的枚举类型实现扩展方法来做到这一点”。

– Peter Mortensen
19/12/8在17:27



#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感到更自在,它可以在很多领域满足这种期望。

#14 楼

int number = Question.Role.GetHashCode();


number的值应为2

评论


GetHashCode是从枚举通用掩码获取值的一种方法

– ThanhLD
18年9月9日在4:08

请注意,对于bool *,byte,ushort,int和uint **,这只是“合法”。其他类型的GetHashCode修改值,例如做一些移位和异或。 (* 1/0,**当然是强制转换为int的)。但是总的来说,除非是您自己的私人代码,否则请不要这样做。

– AnorZaken
2月18日下午13:57

#15 楼

您可以通过对定义的枚举类型实现扩展方法来做到这一点:

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


评论


Bronek,您所做的是通过(非通用btw)扩展方法弥补了信息性语法的不足,而该方法实际上需要花费更长的时间来编写。我看不出它比Tetraneutron的原始解决方案更好。让我们不要聊天,在stackoverflow中总是欢迎您提供帮助,这里的每个人都在这里为您提供帮助。请把我的评论视为建设性批评。

–本杰明·格伦鲍姆(Benjamin Gruenbaum)
2012年12月10日,0:28

本杰明,首先,您为什么删除我的评论?我不理解您的决定-也许社区中的其他人也会同意我的评论。其次,我的解决方案将Tetraneutron的解决方案包裹了起来,准确地说,它更容易写,而且写得更少,因为扩展方法是由IntelliSense建议的。因此,我认为您的决定并不公正且不具有代表性。我在Stack上看到很多类似的答案,也可以。无论如何,我使用我的解决方案,也许将来有人会选择我的解决方案,但是这些负面点使我们很难找到。所有这些都是正确的,不能复制。

–布隆克
2012年12月10日下午3:20

@Bronek如果您不对我执行ping操作,则不会显示您已答复。我没有删除您没有的能力或想要删除的评论。可能有一个mod删除了它-欢迎您标记它以引起管理员注意,并询问原因或更好的方法-询问Meta Stack Overflow。从编程的角度来看,我对您的解决方案有完全正确的看法-这是注释的开头,无需个人化。

–本杰明·格伦鲍姆(Benjamin Gruenbaum)
2013年8月7日14:45

#16 楼

请改用扩展方法:

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


使用起来更漂亮:

var intValue = Question.Role.IntValue();


#17 楼

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


评论


示例代码的解释应有条理(通过编辑答案,而不是在注释中)。

– Peter Mortensen
19/12/8在17:42



通常在枚举中为未设置/未知状态保留零,这是不寻常的定义

–乍得格兰特
19/12/27在18:59

#18 楼

使用:

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


它将产生value == 2

仅当枚举适合int时,这才成立。

评论


这仅在枚举当然适合int时才是正确的,因为GetHashCode返回一个整数。

– RB。
19年8月14日在14:59

#19 楼

由于可以用多种基本类型声明枚举,所以泛型转换任何枚举类型的通用方法都很有用。

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;


#20 楼

以下是扩展方法

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


#21 楼

我能想到的最简单的解决方案是像这样重载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);
    }
}


#22 楼

我最喜欢的具有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


免责声明:

它不适用于枚举基于长期。

#23 楼

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

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


#24 楼

我想建议的示例“从枚举中获取'int'值”是

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

int answer = (int)Sample.Book;


现在答案将是1。

#25 楼

用途:

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


#26 楼

在Visual Basic中,它应该是:

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

Private value As Integer = CInt(Question.Role)


评论


问题是针对C#的。

– Ctrl S
18年11月19日在13:37

标题显示“从C#枚举中获取int值”。

– Peter Mortensen
19/12/8在17:33

#27 楼

您应该已经使用类型转换,就像我们可以在其他任何语言中使用的一样。
如果您的enum像这样-
public enum Question
{
    Role = 2,
    ProjectFunding = 3,
    TotalEmployee = 4,
    NumberOfServers = 5,
    TopBusinessConcern = 6
}

并且您需要转换为int,然后执行此操作-
Question q = Question.Role;
.............
.............
int something = (int) q;

Re-
在C#中,有两种类型的转换:


隐式转换(自动)-将较小的类型转换为较大的尺寸like-


char-> int-> long-> float-> double



显式铸造(手动)-转换较大的类型到较小的类型,例如-


double-> float-> long-> int-> char

更多内容可以在这里找到。

#28 楼

我想出了这种扩展方法,其中包括当前的语言功能。通过使用动态,我不需要使它成为通用方法并指定使调用更简单和一致的类型:

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


评论


请不,您可以在一行中完成所有这些操作。Convert.Changetype(e,e.GetTypeCode())并返回一个对象,不需要动力学或扩展方法

–乍得格兰特
19/12/27在19:05



我不同意使用Convert。仅使用演员表会更容易。我的意图是能够在不使用强制转换的情况下将任何枚举转换为其值。这允许更改枚举类型,而不必更改所有关联的强制类型转换-但是什么时候发生?扩展方法可以正常工作。但是,我有一个问题,因为它是动态的,所以编译器无法进行类型检查(显然是整个语句),这意味着在运行时进行类型检查-不是一个好的解决方案。我想我会回到演员表。

–杰夫
2月22日20:19

我并不是说要在强制转换中使用它,只是因为这段代码是荒谬的,什么也不做,实际上使问题变得更糟。我建议删除此解决方案

–乍得格兰特
2月22日20:44