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

jim 1698 c# int enums casting

我有一个叫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)

Tetraneutron.. 2206

刚刚施放枚举,例如

int something = (int) Question.Role;

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

但是,正如cecilphillip指出的那样,枚举可以有不同的底层类型.如果枚举被声明为uint,long,或ulong,应当投射到枚举的类型; 例如

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

你应该使用

long something = (long)StarsInMilkyWay.Wolf424B;

  • @Sinthia V他说你可以*创建它而不用铸造,这是正确的 (46认同)
  • @Jaider`(int)Test.Item`这是演员!()是显式强制转换运算符. (33认同)
  • @Harry这不是真的.您可以在不进行强制转换的情况下创建枚举,但这不是必需的.我只在特殊情况下分配号码,大多数情况下,我将其保留为默认值.但你可以做`enum Test {Item = 1}`并看到`1 ==(int)Test.Item`是相等的. (23认同)
  • 如果`enum Question`的基础类型不是`int`而是`long`,那么这个强制转换将截断`Role`s积分值! (6认同)

cecilphillip.. 291

由于枚举可以是任何整数类型(byte,int,short等),更鲁棒的方式来获得的枚举的基本积分值将是使使用的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但这是一个不同的故事)的泛型类型时,这种技术证明了它的价值. (31认同)
  • @TimAbell在一个单独的场合,显影剂删除过时的/未使用的枚举值使所述序列中的所有其它值被一个要出.因此,我们的编码标准现在要求ID始终明确规定,否则添加/删除,甚至自动格式化代码(例如按字母顺序排序),将改变导致数据损坏的所有值.我强烈建议任何人明确指定所有Enum整数.如果它们与外部(数据库)存储的值相关,则这是非常重要的. (4认同)
  • 我认为您应该将示例更改为`object val = Convert ... etc`,示例中的`var`将始终为`object`. (2认同)
  • @TimAbell所有我能说的是,我们发现动态编译的aspx页面(你必须将.cs文件部署到实时服务器)是为每个值分配不同的整数.这意味着一台机器上的序列化对象在不同的​​机器上使用不同的值进行反序列化并且有效地被破坏(导致*小时*混乱).我们用MS提出它,我似乎记得他们说当在不同的框架版本中构建时,自动生成的整数不能保证是相同的. (2认同)

小智.. 189

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

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

  • 这种解决方案实际上并没有提供强类型枚举的真正好处.例如,如果我只想将GameState-enum-parameter传递给特定方法,则编译器不应允许我将任何int-variable作为参数传递. (91认同)
  • 我使用`static readonly int`,因为常量被编译成它们的硬值.请参见http://stackoverflow.com/a/755693/492 (29认同)
  • @CADBloke这也正是因为每次你比较`静态readonly`你正在做一个方法调用来获取变量的值,而你会使用`const`而不是`静态readonly`一个`const`你直接比较两种值类型. (10认同)
  • 我很惊讶这没有得到更多的选票 - 如果你真的想在本机上使用int类型那么显而易见. (8认同)
  • @ brettof86是的,const会更快,如果编译限制永远不会有问题,那么它就是好的. (3认同)

jerryjvl.. 83

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

会导致value == 2.

  • 临时变量问题是不必要的. (33认同)
  • 你可以简单地向两个方向投掷; 唯一要注意的是枚举不执行任何操作(枚举值可能是288,即使该数字不存在问题) (6认同)

nawfal.. 77

在相关的说明中,如果您想从中获取intSystem.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);

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


Michael Petr.. 40

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

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

  • Nitpick:*这个*枚举已经是一个int.其他枚举可能是不同的类型 - 尝试"枚举SmallEnum:byte {A,B,C}" (15认同)
  • 绝对真实.C#reference:"每个枚举类型都有一个底层类型,除了char之外,它可以是任何整数类型." (9认同)

小智.. 32

例:

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.

  • 这实际上是编译吗? (6认同)
  • 我很确定在'Raj = 1`之后会出现昏迷,并且`Public Enum`应该是`public enum` (4认同)

JohnLBevan.. 27

我最近在代码中转而使用枚举,转而使用带有受保护构造函数和预定义静态实例的类(感谢Roelof - C# Ensure Valid Enum Values - Futureproof Method).

鉴于此,下面是我现在如何解决这个问题(包括隐式转换为/来自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表达式主体定义.查看原始代码的修订历史记录.这样做的好处是使定义不那么冗长; 这是对这个答案方法的主要抱怨之一.

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

小智.. 19

如果你想得到一个存储在一个变量中的枚举值的整数,那个类型就是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.

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

  • 在荷兰编码。噢亲爱的。 (3认同)

小智.. 15

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

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

我希望这有帮助.


小智.. 14

也许我错过了它,但有人试过一个简单的通用扩展方法.这对我很有用.您可以通过这种方式避免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;
    }
}    


plavozont.. 13

还有一种方法:

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

将导致:

Name: Role, Value: 2


Knickerless-.. 12

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可以满足许多领域的这种期望.


Bronek.. 10

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

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中总是欢迎帮助,这里的每个人都在这里提供帮助.请把我的评论作为建设性的批评. (4认同)
  • 本杰明,首先,你为什么要删除我的意见?我不明白你的决定,也许别人通过社区将与我的comment.Secondly同意,我的解决方案包Tetraneutron的一个,准确这是因为更容易,更写作扩展方法是由IntelliSense.So建议,我认为你的决定是不公平和representative.I看到堆栈许多类似的回答,这是OK.Anyway我用我的解决方案,也许有一些人会选择我未来的解决方案,但这些负面因素使得它更难找到.最重要的是它是正确的而不是复制. (2认同)
  • @Bronek如果你不ping我,我没有表示你回答.我确实_not_删除你的评论我没有能力或想要这样做.可能是一个mod并且删除了它 - 欢迎你将它标记为主持人注意并询问为什么或更好 - 请问[meta].我从编程角度对你的解决方案有一个看法,这完全在我的右边 - 这是评论的开头,不需要把它当作个人的. (2认同)

小智.. 10

int number = Question.Role.GetHashCode();

number应该有价值2.


SixOThree.. 8

如何改为扩展方法:

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

而且用法稍微漂亮一些:

var intValue = Question.Role.IntValue();


Gauravsa.. 7

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


小智.. 5

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

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;


归档时间:

查看次数:

1417161 次

最近记录:

10 月 前