Получить значение 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)
Другие вопросы по тегам