Получить значение int из enum в C #

1387

У меня есть класс под названием 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)?

  • 24
    Для наоборот: приведение к перечислению .
  • 6
    Я знаю, что опаздываю на вечеринку, но вместо того, чтобы определять свой метод как get(int foo) вы можете определить его как get(Question foo) затем выполнить кастинг внутри метода, вы можете вызвать свой метод как Questions.Get(Question.Role)
Теги:
casting
enums
int

25 ответов

1902
Лучший ответ

Просто введите перечисление, например.

int something = (int) Question.Role;

Вышеупомянутое будет работать для подавляющего большинства перечислений, которые вы видите в дикой природе, так как основной тип для перечисления по умолчанию - int.

Однако, как указывает cecilphillip, перечисления могут иметь разные базовые типы. Если перечисление объявлено как uint, long или ulong, оно должно быть передано типу перечисления; например для

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

вы должны использовать

long something = (long)StarsInMilkyWay.Wolf424B;
  • 23
    @ Гарри, это не правда. Вы можете создать перечисление без приведения, это не обязательно. и я назначаю номер только в особых случаях, большую часть времени, я оставляю его как значение по умолчанию. но вы можете сделать enum Test { Item = 1 } и увидеть, что 1 == (int)Test.Item равен.
  • 31
    @Jaider (int)Test.Item Это актерский состав! () - явный оператор приведения.
Показать ещё 8 комментариев
239

Так как Enums могут быть любым интегральным типом (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);

Это должно работать независимо от базового интегрального типа.

  • 25
    Этот метод доказал свою ценность для меня при работе с универсальным типом, где T: enum (на самом деле T: struct, IConvertible, но это другая история).
  • 1
    Как бы вы изменили это, чтобы распечатать шестнадцатеричное значение стороны? Этот пример показывает десятичное значение. Проблема в том, что var относится к типу object , поэтому вам нужно распаковать его, и он станет более грязным, чем мне бы хотелось.
Показать ещё 12 комментариев
174

Объявите его как статический класс с общедоступными константами:

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 или все, что вы его определяете.

  • 7
    Я удивлен, что у него нет больше голосов - это так очевидно, если вы действительно хотите использовать тип int изначально.
  • 29
    Я бы использовал static readonly int потому что константы компилируются в свои жесткие значения. См. Stackoverflow.com/a/755693/492
Показать ещё 10 комментариев
77
Question question = Question.Role;
int value = (int) question;

В результате получится value == 2.

  • 31
    Вопрос о временной переменной не нужен.
  • 1
    Так что-то вроде этого Questions.Get (Convert.ToInt16 (Question.Applications))
Показать ещё 7 комментариев
56

В соответствующем примечании, если вы хотите получить значение 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);

Последние два являются уродливыми. Я предпочитаю первый.

34

Это проще, чем вы думаете - перечисление уже является int. Просто нужно напомнить:

int y = (int)Question.Role;
Console.WriteLine(y); // prints 2
  • 14
    Nitpick: это перечисление уже int. Другие перечисления могут быть разных типов - попробуйте "enum SmallEnum: byte {A, B, C}"
  • 9
    Абсолютная правда. Ссылка C #: «Каждый тип перечисления имеет базовый тип, который может быть любым целым типом, кроме char».
25

Пример:

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

Enums увеличится на 1, и вы можете установить начальное значение. Если вы не установили начальное значение, оно будет первоначально назначено на 0.

  • 6
    Это на самом деле компилируется?
  • 0
    Может ли что-то, что является Раджем, также быть Рахулом или Приянкой? Ваши ценности конфликтуют и должны удваиваться, чтобы быть уникальными, например, 0, 1, 2, 4, 8 и т. Д. Это моя основная проблема с перечислениями.
Показать ещё 1 комментарий
19

Недавно я отказался от использования перечислений в своем коде вместо использования классов с защищенными конструкторами и предопределенными статическими экземплярами (благодаря Roelof - С# Обеспечить допустимые значения перечисления - метод будущего).

В свете этого ниже, как я теперь подхожу к этой проблеме (включая неявное преобразование в/из 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), в отличие от того, чтобы приводить множество описаний случаев в вашем коде для решения каждого сценария.


NB: ответ обновлен 2018-04-27, чтобы использовать функции С# 6; т.е. выражений декларации и выражений тела лямбда-выражения. См. Историю изменений для исходного кода. Это имеет смысл сделать определение немного менее подробным; которая была одной из основных жалоб на этот подход ответа.

  • 1
    Я предполагаю, что это компромисс между явным приведением и кодом, который вы должны написать, чтобы обойти его. Все еще люблю реализацию, просто жаль, что это не было так долго. +1
  • 1
    Я использовал несколько различных типов классов, структурированных аналогично этому. Я нахожу, что они творят чудеса, пытаясь следовать методологии «не дай мне быть идиотом позже».
16

Если вы хотите получить целое число для значения перечисления, которое хранится в переменной, тип которой будет 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.

Мне было трудно найти это простое решение в Интернете, и я не смог его найти, поэтому я что-то тестировал и нашел это. Надеюсь это поможет.;)

  • 1
    кодирование на голландском. о, Боже.
  • 0
    К сожалению, такой подход дает плохую производительность, чем больше вы используете его. Я попробовал это в некотором моем коде, и со временем мое приложение становилось все медленнее и медленнее, с все меньшим использованием процессора. Это подразумевало, что потоки чего-то ожидали - я предполагаю какую-то сборку мусора, возможно, из-за помещения параметра enum в ToInt32 (). Переключившись на простой int.Parse (), я смог полностью устранить эту низкую производительность, и производительность осталась прежней, независимо от того, как долго выполнялся код.
14

Чтобы гарантировать, что значение 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 corresponding DOW enum object.
    enmDOW = (DayOfWeek)Enum.Parse(typeof(DayOfWeek), strDOWReal);
}

// Can now use the DOW enum object.
Console.Write("Today is " + enmDOW.ToString() + ".");

Надеюсь, это поможет.

11

Возможно, я пропустил это, но кто-нибудь пробовал простой общий метод расширения. Это отлично работает для меня. Вы можете избежать применения типа в вашем 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;
    }
}    
  • 0
    Возможно, потому что выполнение (int) customFlag меньше набирает текст и делает более или менее одно и то же?
11

Еще один способ сделать это:

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

приведет к:

Name: Role, Value: 2
10
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
}

Это менее элегантно, чтобы объявить, но вам не нужно указывать его в коде:

int Question = QuestionType.Role

В качестве альтернативы вы можете чувствовать себя более комфортно с Visual Basic, который удовлетворяет ожиданиям такого типа во многих областях.

9
int number = Question.Role.GetHashCode();

number должно иметь значение 2.

  • 0
    GetHashCode - это один из способов получить значение из общей маски Enum.
9

Вы можете сделать это, внедрив метод расширения в свой определенный тип перечисления:

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();
  • 4
    Бронек, то, что вы сделали, это создали неинформативный синтаксис с помощью метода расширения (не универсального, кстати), который на самом деле занимает больше времени для записи. Я не вижу, как это лучше, чем оригинальное решение от Tetraneutron. Давайте не будем превращать это в чат, помощь всегда приветствуется в stackoverflow, и все здесь, чтобы помочь. Пожалуйста, примите мой комментарий как конструктивную критику.
  • 2
    Бенджамин, во-первых, почему ты удалил мой комментарий? Я не понимаю твоих решений - может быть, кто-то другой из сообщества согласится с моим комментарием. Во-вторых, мое решение обернуло одно из Tetraneutron, и оно точно и легче, и меньше написано, потому что IntelliSense предлагает метод расширения. Так что я думаю, что ваше решение не является беспристрастным и репрезентативным. Я вижу много аналогичных ответов по стеку, и это нормально. В любом случае, я использую свое решение, и, возможно, некоторые люди выберут мое решение в будущем, но эти негативные моменты затрудняют поиск. Больше всего это правильно, а не копировать.
Показать ещё 1 комментарий
6

Как насчет метода расширения:

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

И использование немного красивее:

var intValue = Question.Role.IntValue();
3

Ниже приведен метод расширения

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

Мой fav-хак с 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    

Отказ от ответственности: Не работает для перечислений на основе длинных

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

Поскольку перечисления могут быть объявлены с несколькими примитивными типами, может быть полезен общий метод расширения для создания любого типа перечислений.

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;
2

В примере, который я хотел бы предложить "получить значение" int "из перечисления,"

public enum Sample
{Book =1, Pen=2, Pencil =3}

int answer = (int)Sample.Book;

теперь ответ будет 1.

Я надеюсь, что это может помочь кому-то.

1

В Vb. Это должно быть

Public Enum Question
    Role = 2
    ProjectFunding = 3
    TotalEmployee = 4
    NumberOfServers = 5
    TopBusinessConcern = 6
End Enum

Private value As Integer = CInt(Question.Role)
  • 0
    Вопрос к C #.
1

Попробуйте это вместо преобразования enum в int:

public static class ReturnType
{
    public static readonly int Success = 1;
    public static readonly int Duplicate = 2;
    public static readonly int Error = -1;        
}
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);
    }
}
-14

Попробуйте следующее:

int value = YourEnum.ToString("D");

Ещё вопросы

Сообщество Overcoder
Наверх
Меню