提问人:jim 提问时间:6/3/2009 最后编辑:jim 更新时间:6/29/2023 访问量:2282799
从 C 中的枚举中获取 int 值#
Get int value from enum in C#
问:
我有一个名为(复数)的类。在这个类中,有一个叫做(单数)的枚举,它看起来像这样。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)
答:
Question question = Question.Role;
int value = (int) question;
将导致 .value == 2
评论
只需转换枚举,例如
int something = (int) Question.Role;
以上方法适用于您在野外看到的绝大多数枚举,因为枚举的默认基础类型是 。int
然而,正如 cecilphillip 所指出的,枚举可以有不同的基础类型。
如果枚举被声明为 、 或 ,则应将其转换为枚举的类型;例如,对于uint
long
ulong
enum StarsInMilkyWay:long {Sun = 1, V645Centauri = 2 .. Wolf424B = 2147483649};
你应该使用
long something = (long)StarsInMilkyWay.Wolf424B;
评论
enum Test { Item = 1 }
1 == (int)Test.Item
(int)Test.Item
enum Question
int
long
Role
Enum
int
int
这比你想象的要容易 - 枚举已经是一个 int。只需要提醒一下:
int y = (int)Question.Role;
Console.WriteLine(y); // Prints 2
评论
例:
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。
评论
1
int
由于枚举可以是任何整数类型(、、等),因此获取枚举的基础整数值的更可靠的方法是将该方法与类结合使用: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);
无论基础整数类型如何,这都应该有效。
评论
var
object
若要确保枚举值存在,然后对其进行分析,还可以执行以下操作。
// 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() + ".");
如果你想获取存储在变量中的枚举值的整数,其类型将是 ,例如在方法中使用,你可以简单地执行我在这个例子中写的: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,因为变量是 .如果我将其更改为并再次调用该方法,则文本将更改为 3。Geselecteerd
Talen.Nederlands
Talen.Portugees
评论
将其声明为具有公共常量的静态类:
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
评论
const
static readonly
static readonly
const
compilation limitation
为此,可以对定义的枚举类型实现扩展方法:
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();
评论
我能想到的最简单的解决方案是像这样重载方法: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);
}
}
我最近从在代码中使用枚举转变为使用具有受保护构造函数和预定义静态实例的类(感谢 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)
}
这种方法的优点是你可以从枚举中获得你所拥有的一切,但你的代码现在更加灵活,所以如果你需要根据 的值执行不同的操作,你可以把逻辑放进去(即以首选的 OO 方式),而不是在整个代码中放大量的 case 语句来处理每个场景。Question
Question
注意:答案更新于 2018-04-27 以利用 C# 6 功能;即声明表达式和 lambda 表达式正文定义。请参阅原始代码的修订历史记录。这样做的好处是使定义不那么冗长;这是对这个答案方法的主要抱怨之一。
评论
与此相关的是,如果要从 中获取值,则此处给出: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);
最后两个简直太丑了。我更喜欢第一个。
评论
Cannot convert type 'System.Enum' to 'int'
试试这个,而不是将枚举转换为 int:
public static class ReturnType
{
public static readonly int Success = 1;
public static readonly int Duplicate = 2;
public static readonly int Error = -1;
}
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 感到更满意,因为它在许多方面都满足了这种类型的期望。
请改用扩展方法:
public static class ExtensionMethods
{
public static int IntValue(this Enum argEnum)
{
return Convert.ToInt32(argEnum);
}
}
而且用法稍微漂亮一些:
var intValue = Question.Role.IntValue();
int number = Question.Role.GetHashCode();
number
应具有值。2
评论
bool
byte
ushort
int
uint
还有一种方法:
Console.WriteLine("Name: {0}, Value: {0:D}", Question.Role);
这将导致:
Name: Role, Value: 2
评论
也许我错过了它,但有没有人尝试过简单的通用扩展方法?
这对我来说很有效。您可以通过这种方式避免 API 中的类型转换,但最终会导致更改类型操作。这是一个很好的案例,用于对 Roslyn 进行编程,让编译器为你创建 GetValue<T> 方法。
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 或更小枚举的技巧:
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
免責聲明:
它不适用于基于 long 的枚举。
我想建议“从枚举中获取'int'值”的例子是
public enum Sample
{
Book = 1,
Pen = 2,
Pencil = 3
}
int answer = (int)Sample.Book;
现在答案将是 1。
在 Visual Basic 中,它应该是:
Public Enum Question
Role = 2
ProjectFunding = 3
TotalEmployee = 4
NumberOfServers = 5
TopBusinessConcern = 6
End Enum
Private value As Integer = CInt(Question.Role)
以下是扩展方法
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;
}
由于枚举可以使用多个基元类型声明,因此用于强制转换任何枚举类型的泛型扩展方法可能很有用。
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;
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);
}
评论
我想出了这个包含当前语言功能的扩展方法。通过使用 dynamic,我不需要将其设置为通用方法并指定使调用更简单和一致的类型:
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;
}
评论
用:
Question question = Question.Role;
int value = question.GetHashCode();
这将导致 .value == 2
仅当枚举适合 .int
评论
int
GetHashCode
您应该使用类型转换,因为我们可以在任何其他语言中使用。
如果你是这样的——enum
public enum Question
{
Role = 2,
ProjectFunding = 3,
TotalEmployee = 4,
NumberOfServers = 5,
TopBusinessConcern = 6
}
你需要投射到一个,然后这样做——int
Question q = Question.Role;
.............
.............
int something = (int) q;
再-
在 C# 中,有两种类型的强制转换:
- 隐式强制转换(自动) - 将较小的类型转换为较大的类型大小,例如-
char
->int
->long
->float
->double
- 显式转换(手动) - 将较大的类型转换为较小尺寸的类型,例如-
double
->float
->long
->int
->char
更多信息可以在这里找到。
将为您提供包含枚举的所有整数值的列表:
列表 enumValues = Enum.GetValues(typeof(EnumClass))。Cast()。ToList();
public enum ViewType
{
List = 1,
Table = 2,
};
// You can use the Enum type as a parameter, so any enumeration from any enumerator
// cshtml
// using proyects.Helpers
// @if (Model.ViewType== (int)<variable>.List )
几乎所有当前答案都使用或强制转换为目标类型之前的对象,这会导致装箱和取消装箱操作。这会导致堆分配,并且对于热路径可能不可接受。Convert
由于这些答案中的大多数都是编写的,因此引入了 System.Runtime.CompilerServices.Unsafe,从而实现了指针的低级操作。
结合泛型,该类允许我们安全地更改参数的基础类型,零分配,并且性能与空方法持续时间几乎无法区分:Unsafe
System.Enum
public long GetEnumValue<T>(T enumInstance) where T : unmanaged, Enum
{
var size = Unsafe.SizeOf<T>();
if (size == Unsafe.SizeOf<byte>())
{
return Unsafe.As<T, byte>(ref enumInstance);
}
else if (size == Unsafe.SizeOf<short>())
{
return Unsafe.As<T, short>(ref enumInstance);
}
else if (size == Unsafe.SizeOf<int>())
{
return Unsafe.As<T, int>(ref enumInstance);
}
else if (size == Unsafe.SizeOf<long>())
{
return Unsafe.As<T, long>(ref enumInstance);
}
return -1; // or throw if you prefer
}
如果最好总是返回一个 int,你可以这样做,尽管如果枚举的支持字段超过 ,它将溢出:int.MaxValue
public int GetEnumValue<T>(T enumInstance) where T : unmanaged, Enum
{
var size = Unsafe.SizeOf<T>();
if (size == Unsafe.SizeOf<byte>())
{
return Unsafe.As<T, byte>(ref enumInstance);
}
else if (size == Unsafe.SizeOf<short>())
{
return Unsafe.As<T, short>(ref enumInstance);
}
else if (size == Unsafe.SizeOf<int>())
{
return Unsafe.As<T, int>(ref enumInstance);
}
else if (size == Unsafe.SizeOf<long>())
{
return Unsafe.As<T, int>(ref enumInstance);
}
return -1; // or throw if you prefer
}
如果使用以下方法:
public enum EnumLong : long
{
First,
Second,
Third = (long)(int.MaxValue) + 1
}
var val = GetEnumValue(EnumLong.Third);
-2147483648
将由于溢出而返回。开发人员极不可能创建具有如此大标志值的枚举,但始终有可能。
public int QuestionToInt(Question q)
{
return (int)q;
}
评论
get(int foo)
get(Question foo)
Questions.Get(Question.Role)