У меня есть класс под названием 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 something = (int) Question.Role;
Вышеописанное будет работать для подавляющего большинства перечислений, встречающихся в природе, поскольку по умолчанию базовым типом для перечисления является int
.
Однако, как отмечает cecilphillip, перечисления могут иметь разные базовые типы.
Если перечисление объявлено как uint
, long
или ulong
, оно должно быть приведено к типу перечисления; например, для
enum StarsInMilkyWay:long {Sun = 1, V645Centauri = 2 .. Wolf424B = 2147483649};
следует использовать
long something = (long)StarsInMilkyWay.Wolf424B;
После перечисления может быть любой целочисленный тип (байт
, инт
, короткий
, и т. д.), более надежный способ получить базовое интегральное значение перечисления можно было бы использовать GetTypeCode
метод в сочетании с "конвертировать" класса:
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;
}
И тогда вы можете ссылаться на него, как вопрос.Роль, и он всегда оценивает к
int` или все, что вы определяете его как.
На соответствующую записку, Если вы хотите получить на int
значение `системы.Перечисление, затем дается " е " здесь:
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);
Последние два простой некрасиво. Я предпочитаю первый.
Это проще, чем вы думаете - enum уже является int. Просто нужно напомнить об этом:
int y = (int)Question.Role;
Console.WriteLine(y); // prints 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, и вы можете установить начальное значение. Если вы Don't установите значение параметра Start, сначала он будет назначен 0.
Я недавно принял от использования перечислений в мой код в пользу, а не используя классы с защищенных конструкторов и предопределенные статические экземпляры (спасибо Рулоф - https://stackoverflow.com/questions/10704863/c-sharp-ensure-valid-enum-values-futureproof-method).
В свете этого, ниже's, как я'd теперь подходить к этому вопросу (включая неявное преобразование из типа 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)
}
Преимущество этого подхода-вы получаете все, что бы из enum, но ваш код's теперь гораздо более гибким, так что если вам необходимо выполнять различные действия на основе значения вопрос
, вы можете поместить логику в вопрос
себя (т. е. в предпочтительном ОО мода), а не класть много операторов по всему коду для решения каждого сценария.
Примечание: ответ обновлен 2018-04-27 для использования в C# 6 функции; т. е. декларация выражений и лямбда-выражения тела, определения. См. история изменений для исходного кода. Это имеет то преимущество, что делает определение немного менее многословный; которая была одной из главных жалоб на это ответ'ы подход.
Если вы хотите получить целочисленное значение перечисления, которое хранится в переменной, которая типа будет вопрос
, чтобы использовать, например, в метод, вы можете просто это сделать, я писал в этом примере:
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 переменной `это
Тален.Голландия. Если я измените его на
Тален.Магере и снова вызвать метод, текст изменится на 3.
Я имел трудное время, находя это простое решение проблемы в интернете и я не мог'т найти его, поэтому я был что-то испытывать и узнал об этом. Надеюсь, что это помогает. ;)
Для обеспечения существует значение типа 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() + ".");
Я надеюсь, что это помогает.
Может быть, я пропустил это, но кто-нибудь пробовал простой универсальный способ расширения. Это прекрасно работает для меня. Вы можете избежать приведения типов в API этот путь, но в конечном счете это приводит к изменению типа операции. Это хороший случай для программирования Розелин иметь компилятор сделает Думою в<Т> способ для вас.
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;
}
}
public enum QuestionType
{
Role = 2,
ProjectFunding = 3,
TotalEmployee = 4,
NumberOfServers = 5,
TopBusinessConcern = 6
}
...является прекрасным декларации.
Вы должны привести результат к int, как так:
int Question = (int)QuestionType.Role
В противном случае, этот тип еще QuestionType`.
Этот уровень строгости в сторону.
Одной из альтернатив является использование вместо объявлении класса:
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
}
Это's не менее элегантно объявить, но вы Don'т нужна, чтобы бросить его в код:
int Question = QuestionType.Role
Кроме того, вы можете чувствовать себя более комфортно с Visual Basic, который предназначен для этого типа ожидания во многих областях.
int number = Question.Role.GetHashCode();
количество
должен иметь значение 2
.
Вы можете сделать это путем реализации метод расширения в указанный перечислимый тип:
public static class MyExtensions
{
public static int getNumberValue(this Question questionThis)
{
return (int)questionThis;
}
}
Это упростит получение значение из текущего значения enum:
Question question = Question.Role;
int value = question.getNumberValue();
или
int value = Question.Role.getNumberValue();
Как насчет того, чтобы метод расширения:
public static class ExtensionMethods
{
public static int IntValue(this Enum argEnum)
{
return Convert.ToInt32(argEnum);
}
}
И использование немного красивее:
var intValue = Question.Role.IntValue();
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);
}
После перечисления могут быть объявлены с нескольких примитивных типов, универсальный метод расширения, чтобы бросить любого перечислимого типа могут быть полезны.
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 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;
}
Мой Хак ФАВ с 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
Предупреждение: Не't работа для перечислений на основе