Получить значение int из enum в 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)
?
34 ответа
Просто приведите enum, например
int something = (int) Question.Role;
Вышеприведенное будет работать для подавляющего большинства перечислений, которые вы видите в дикой природе, поскольку базовый тип по умолчанию для перечисления int
,
Однако, как указывает cecilphillip, перечисления могут иметь разные базовые типы. Если перечисление объявлено как uint
, long
, или же ulong
, он должен быть приведен к типу перечисления; например для
enum StarsInMilkyWay:long {Sun = 1, V645Centauri = 2 .. Wolf424B = 2147483649};
ты должен использовать
long something = (long)StarsInMilkyWay.Wolf424B;
Поскольку перечисления могут быть любого целочисленного типа (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);
Это должно работать независимо от базового целочисленного типа.
Объявите его как статический класс, имеющий открытые константы:
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
значение от 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);
Последние два просто безобразны. Я предпочитаю первый.
Question question = Question.Role;
int value = (int) question;
Приведет к value == 2
,
Пример:
public Enum EmpNo
{
Raj = 1,
Rahul,
Priyanka
}
И в коде, чтобы получить значение enum:
int setempNo = (int)EmpNo.Raj; //This will give setempNo = 1
или же
int setempNo = (int)EmpNo.Rahul; //This will give setempNo = 2
Перечисления будут увеличиваться на 1, и вы можете установить начальное значение. Если вы не установите начальное значение, оно будет изначально присвоено как 0.
Это проще, чем вы думаете - перечисление уже int. Это просто нужно напомнить:
int y = (int)Question.Role;
Console.WriteLine(y); // prints 2
Недавно я перешел от использования перечислений в моем коде в пользу использования классов с защищенными конструкторами и предопределенными статическими экземплярами (благодаря Roelof - C# Enure 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
сам по себе (то есть в предпочтительном режиме ОО), а не помещает в регистр множество операторов case для решения каждого сценария.
NB: Ответ обновлен 2018-04-27, чтобы использовать функции C# 6; то есть выражения объявления и определения тела лямбда-выражения. Смотрите историю изменений для оригинального кода. Это дает преимущество, делая определение немного менее многословным; которая была одной из основных жалоб на подход этого ответа.
Если вы хотите получить целое число для значения enum, которое хранится в переменной, тип которого будет 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, потому что переменная Geselecteerd
является Talen.Nederlands
, Если я изменю это на Talen.Portugees
и вызовите метод снова, текст изменится на 3.
Мне было трудно найти это простое решение в Интернете, и я не смог его найти, поэтому я что-то тестировал и выяснил это. Надеюсь это поможет.;)
Как насчет метода расширения:
public static class ExtensionMethods
{
public static int IntValue(this Enum argEnum)
{
return Convert.ToInt32(argEnum);
}
}
И использование немного красивее:
var intValue = Question.Role.IntValue();
Еще один способ сделать это:
Console.WriteLine("Name: {0}, Value: {0:D}", Question.Role);
Приведет к:
Name: Role, Value: 2
Чтобы убедиться, что значение enum существует, а затем проанализировать его, вы также можете сделать следующее.
// 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 question = Question.Role;
int value = question.GetHashCode();
Это приведет к value == 2
.
Это верно только в том случае, если перечисление помещается внутри int
.
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, который обслуживает такого рода ожидания во многих областях.
Возможно я пропустил это, но кто-нибудь пробовал простой общий метод расширения. Это прекрасно работает для меня. Таким способом вы можете избежать приведения типов в вашем 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;
}
}
int number = Question.Role.GetHashCode();
number
должен иметь значение 2
,
Вы можете сделать это, внедрив метод расширения в определенный вами тип перечисления:
public static class MyExtensions
{
public static int getNumberValue(this Question questionThis)
{
return (int)questionThis;
}
}
Это упрощает получение значения int текущего значения enum:
Question question = Question.Role;
int value = question.getNumberValue();
или же
int value = Question.Role.getNumberValue();
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);
}
Мой любимый хак с int или меньшими enums:
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
Отказ от ответственности: не работает для перечислений, основанных на длинных
Поскольку перечисления могут быть объявлены с несколькими примитивными типами, универсальный метод расширения для приведения любого типа перечисления может быть полезен.
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;
Вам следовало использовать приведение типов, как мы можем использовать на любом другом языке.
Если ваш
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
Больше можно найти здесь.
Пример, который я хотел бы предложить 'получить'int'значение из enum,'
public enum Sample
{Book =1, Pen=2, Pencil =3}
int answer = (int)Sample.Book;
теперь ответ будет 1.
Я надеюсь, что это может кому-то помочь.
Самым простым решением, которое я могу придумать, является перегрузка 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);
}
}
Попробуйте это вместо преобразования enum в int:
public static class ReturnType
{
public static readonly int Success = 1;
public static readonly int Duplicate = 2;
public static readonly int Error = -1;
}
Ниже приводится метод расширения
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;
}
Использование:
Question question = Question.Role;
int value = Convert.ToInt32(question);
В Vb. Так должно быть
Public Enum Question
Role = 2
ProjectFunding = 3
TotalEmployee = 4
NumberOfServers = 5
TopBusinessConcern = 6
End Enum
Private value As Integer = CInt(Question.Role)
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.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
будет возвращен из-за переполнения. Крайне маловероятно, что разработчики будут создавать перечисления с такими большими значениями флагов, но это всегда возможно.
enum Talen
{
Engels = 1, Italiaans = 2, Portugees = 3, Nederlands = 4, Duits = 5, Dens = 6
}
Talen Geselecteerd;
// You can use the Enum type as a parameter, so any enumeration from any enumerator
// cshtml
// using proyects.Helpers
// @if (Model.Talen == (int)Talen.Engels)