题 从C#中的枚举中获取int值


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

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

在里面 Questions 上课,我有一个 get(int foo) 返回一个的函数 Questions 对象 foo。有没有一种简单的方法从枚举中获取整数值,所以我可以做类似的事情 Questions.Get(Question.Role)


1374
2018-06-03 06:46


起源


换句话说: 投-INT到枚举在-C-尖锐。 - nawfal
我知道我迟到了,但不是把你的方法定义为 get(int foo) 你可以把它定义为 get(Question foo) 然后在方法内部进行转换,您可以将方法称为 Questions.Get(Question.Role) - Joe


答案:


刚刚施放枚举,例如

int something = (int) Question.Role;

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

但是,作为 cecilphillip 指出,枚举可以有不同的底层类型。 如果枚举被声明为 uintlong, 要么 ulong,它应该被转换为枚举的类型;例如对于

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

你应该使用

long something = (long)StarsInMilkyWay.Wolf424B;

1803
2018-06-03 06:49



哦,来吧,我知道了 enum Test { Item = (int)1 } 我必须在每次使用时施展它吗?羞辱编译器不能为我做。它应该作为隐式转换。但当然不是。 - Harry
@Harry这不是真的。您可以在不进行强制转换的情况下创建枚举,但这不是必需的。我只在特殊情况下分配号码,大多数情况下,我将其保留为默认值。但你可以做到 enum Test { Item = 1 } 并看到 1 == (int)Test.Item 是平等的。 - Jaider
@Jaider (int)Test.Item 那是演员! ()是显式强制转换运算符。 - Sinthia V
@Sinthia V他说你可以 创建 它没有铸造,这是正确的 - Paul Ridgway
如果底层类型为 enum Question 不是 int 但 long 这个演员会截断 Role的积分值! - quaylar


因为Enums可以是任何整数类型(byteintshort等等,获得枚举的基本积分值的更健壮的方法是利用 GetTypeCode 与...相结合的方法 Convert 类:

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

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

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


237
2017-07-09 14:54



在处理T:enum(实际上是T:struct,IConvertible但这是一个不同的故事)的泛型类型时,这种技术证明了它的价值。 - aboy021
你如何修改它来打印出一边的十六进制值?此示例显示十进制值。问题是 var 是类型 object,所以你需要拆箱,它比我想要的更乱。 - Mark Lakata
我认为你应该改变这个例子 object val = Convert...etc 该 var 在你的例子将永远 object。 - Meshette
@TimAbell所有我能说的是,我们发现动态编译的aspx页面(你必须将.cs文件部署到实时服务器)是为每个值分配不同的整数。这意味着一台机器上的序列化对象在不同的​​机器上使用不同的值进行反序列化并且有效地被破坏(导致 小时 混乱)。我们用MS提出它,我似乎记得他们说在不同的框架版本中构建时,自动生成的整数不能保证是相同的。 - NickG
@TimAbell在另一个场合,开发人员删除了一个过时/未使用的Enum值,导致序列中的所有其他值都被一个输出。因此,我们的编码标准现在要求始终明确指定ID,否则添加/删除甚至自动格式化代码(例如按字母顺序排序)将更改导致数据损坏的所有值。我强烈建议任何人明确指定所有Enum整数。如果它们与外部(数据库)存储的值相关,则这是非常重要的。 - NickG


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

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


162
2018-06-15 19:28



我很惊讶这没有更多的选票 - 如果你真的想在本机上使用int类型,这是显而易见的。 - CAD bloke
我用了 static readonly int 因为常量被编译成它们的硬值。看到 stackoverflow.com/a/755693/492 - CAD bloke
这种解决方案实际上并没有提供强类型枚举的真正好处。例如,如果我只想将GameState-enum-parameter传递给特定方法,则编译器不应允许我将任何int-variable作为参数传递。 - thgc
@CADBloke这正是你要使用的原因 const并不是 static readonly 因为你每次比较 static readonly 你正在进行方法调用以获取变量的值,而使用a const 你直接比较两种价值类型。 - blockloop
@ brettof86是的,const会更快,如果编译限制永远不会有问题那么它就是好的。 - CAD bloke


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

会导致 value == 2


72
2018-06-03 06:48



临时变量问题是不必要的。 - Gishu
所以像这样的问题。获取(转换.ToInt16(Question.Applications)) - jim
没有必要转换它 - 只是演员。 - Michael Petrotta
你可以简单地向两个方向投掷;唯一要注意的是枚举不执行任何操作(枚举值可能是288,即使该数字不存在问题) - Marc Gravell♦
@Gishu你可以说这是......有问题的。 ;) - Felix D.


在相关的说明,如果你想得到 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);

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


55
2017-12-01 08:47





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

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

30
2018-06-03 06:51



鸡蛋里挑骨头: 这个 枚举已经是一个int。其他枚举可能是不同的类型 - 尝试“枚举SmallEnum:byte {A,B,C}” - mquander
千真万确。 C#reference:“每个枚举类型都有一个底层类型,除了char之外,它可以是任何整数类型。” - Michael Petrotta


例:

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。


22
2017-09-25 10:43



这实际上是编译吗? - Peter Mortensen
Raj的东西也可以是Rahul或Priyanka吗?你的价值观冲突,应该加倍才能成为唯一的0,1,2,4,8等。这是我对枚举的核心关注。 - Timothy Gonzalez
我很确定之后昏迷了 Raj = 1,和 Public Enum 应该 public enum - Rafalon


我最近在代码中转换为使用枚举而不是使用带有受保护构造函数和预定义静态实例的类(感谢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表达式主体定义。看到 修订记录 原始代码。这样做的好处是使定义不那么冗长;这是对这个答案方法的主要抱怨之一。


18
2018-03-30 01:08



我想这是在显式强制转换和你必须编写以避免它的代码之间的权衡。仍然喜欢实施,只是希望它不是那么冗长。 +1 - Lankymart
我使用了几种与此类似的不同类型的类。当我试图遵循“不要让我成为一个白痴后来”的方法时,我发现他们创造了奇迹。 - James Haug


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

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

我希望这有帮助。


12
2017-07-22 20:56