Получить значение int из перечисления в C#

у меня есть класс с именем Questions (множественное число). В этом классе есть перечисление Question (единственное число), которое выглядит так.

public enum Question
{
    Role = 2,
    ProjectFunding = 3,
    TotalEmployee = 4,
    NumberOfServers = 5,
    TopBusinessConcern = 6
}

на Questions класс, у меня есть get(int foo) функция, которая возвращает

25 ответов


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

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, etc.), более надежным способом получить базовое интегральное значение перечисления было бы использовать 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 или как вы его определяете.


Question question = Question.Role;
int value = (int) question;

в результате value == 2.


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

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


это проще, чем вы думаете - перечисление уже является 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 изначально.


недавно я перешел от использования перечислений в моем коде в пользу использования классов с защищенными конструкторами и предопределенными статическими экземплярами (благодаря 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)
}

преимущество этого подхода заключается в том, что вы получаете все, что у вас было бы от перечисления, но ваш код теперь намного более гибкий, поэтому вам нужно выполнять различные действия, основанные на значении Question, вы можете поместить логику в Question сам (т. е. предпочтительным способом OO), в отличие от размещения множества операторов case во всем коде для решения каждого сценария.


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


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

// 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, потому что переменная Geselecteerd и Talen.Nederlands. Если я изменю его на Talen.Portugees и вызовите метод снова, текст изменится на 3.

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


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

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

в результате:

Name: Role, Value: 2

возможно, я пропустил его, но кто-нибудь пробовал простой общий метод расширения. Это отлично работает для меня. Вы можете избежать приведения типа в 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;
    }
}    

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, который во многих областях этот тип ожидания оправдан.


вы можете сделать это путем реализации Метод Расширения к определенному типу перечисления:

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();

int number = Question.Role.GetHashCode();

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


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

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

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

var intValue = Question.Role.IntValue();

my fav hack с 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    

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


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

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

самое простое решение, которое я могу придумать, - это перегрузка Get(int) способ такой:

[modifiers] Questions Get(Question q)
{
    return Get((int)q);
}

здесь [modifiers] обычно может быть таким же, как для Get(int) метод. Если вы не можете изменить Questions class или по какой-то причине не хотите, вы можете перегрузить метод, написав расширение:

public static class Extensions
{
    public static Questions Get(this Questions qs, Question q)
    {
        return qs.Get((int)q);
    }
}

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

public static class ReturnType
{
    public static readonly int Success = 1;
    public static readonly int Duplicate = 2;
    public static readonly int Error = -1;        
}

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

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

int answer = (int)Sample.Book;

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

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


В Vb. Он должен быть!--2-->

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

Private value As Integer = CInt(Question.Role)

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

        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 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 value = YourEnum.ToString("D");