enums convert - Ottieni un valore int da enum in C#




to integer (21)

Ho una classe chiamata Questions (plurale). In questa classe c'è un enum chiamato Question (singolare) che assomiglia a questo.

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

Nella classe Questions , ho una funzione get(int foo) che restituisce un oggetto Questions per quello foo . C'è un modo semplice per ottenere il valore intero dall'enumerazione così posso fare qualcosa come Questions.Get(Question.Role) ?


Answers

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

Risulterà in value == 2 .


È possibile farlo implementando un metodo di estensione al tipo enum definito:

public static class MyExtensions
{
    public static int getNumberValue(this Question questionThis)
    {
        return (int)questionThis;
    }
}

Questo semplifica l'acquisizione del valore int del valore attuale di enum:

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

o

int value = Question.Role.getNumberValue();

Un altro modo per farlo:

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

Risulterà in:

Name: Role, Value: 2

In Vb. Dovrebbe essere

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

Private value As Integer = CInt(Question.Role)

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

È più facile di quanto pensi - un enum è già un int. Ha solo bisogno di essere ricordato:

int y = (int)Question.Role;
Console.WriteLine(y); // prints 2

Poiché Enum può essere un qualsiasi tipo integrale ( byte , int , short , ecc.), Un modo più efficace per ottenere il valore integrale sottostante GetTypeCode quello di utilizzare il metodo GetTypeCode in combinazione con la classe Convert :

enum Sides {
    Left, Right, Top, Bottom
}
Sides side = Sides.Bottom;

object val = Convert.ChangeType(side, side.GetTypeCode());
Console.WriteLine(val);

Questo dovrebbe funzionare indipendentemente dal tipo integrale sottostante.


Che dire invece di un metodo di estensione:

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

E l'utilizzo è leggermente più bello:

var intValue = Question.Role.IntValue();

L'esempio che vorrei suggerire 'ottenere il valore' int 'da enum è'

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

int answer = (int)Sample.Book;

ora la risposta sarà 1.

Spero che questo possa aiutare qualcuno.


Prova questo :

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

Poiché le enumerazioni possono essere dichiarate con più tipi primitivi, può essere utile un metodo di estensione generico per il cast di qualsiasi tipo di enumerazione.

        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;

Se si desidera ottenere un numero intero per il valore enum memorizzato in una variabile, il cui tipo sarebbe Question , da utilizzare ad esempio in un metodo, è sufficiente eseguire ciò che ho scritto in questo esempio:

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

Questo cambierà il titolo della finestra in 4 perché la variabile Geselecteerd è Talen.Nederlands . Se lo cambio a Talen.Portugees e chiamo di nuovo il metodo, il testo cambierà in 3.

Ho avuto difficoltà a trovare questa semplice soluzione su Internet e non riuscivo a trovarla, quindi stavo testando qualcosa e ho scoperto questo. Spero che questo ti aiuti. ;)


Per garantire che esista un valore enum e quindi analizzarlo, puoi anche fare quanto segue.

// 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() + ".");

Spero che questo possa essere d'aiuto.


int number = Question.Role.GetHashCode();

number dovrebbe avere il valore 2 .


Dichiaralo come una classe statica con costanti pubbliche:

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

E quindi puoi fare riferimento a Question.Role , e sempre valuta un int o qualunque cosa tu definisca come.


Forse l'ho perso ma qualcuno ha provato un semplice metodo di estensione generico. Questo funziona alla grande per me. È possibile evitare il cast del tipo nella propria API in questo modo, ma alla fine risulta un'operazione di tipo change. Questo è un buon caso per programmare Roselyn affinché il compilatore faccia un metodo GetValue per te.

    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
}

... è una bella dichiarazione.

Devi trasmettere il risultato a int come:

int Question = (int)QuestionType.Role

Altrimenti, il tipo è ancora QuestionType .

Questo livello di rigore è il modo C #.

Un'alternativa è usare invece una dichiarazione di classe:

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
}

È meno elegante da dichiarare, ma non è necessario inserirlo nel codice:

int Question = QuestionType.Role

In alternativa, potresti sentirti più a tuo agio con Visual Basic, che soddisfa questo tipo di aspettativa in molte aree.


Recentemente mi sono convertito dall'usare le enumerazioni nel mio codice in favore di usare invece classi con costruttori protetti e istanze statiche predefinite (grazie a Roelof - C # Garantire Valid Enum Values ​​- Futureproof Method ).

Alla luce di ciò, di seguito è come vorrei ora affrontare questo problema (compresa la conversione implicita in / da 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)
}

Il vantaggio di questo approccio è che ottieni tutto ciò che vorresti dall'enumerazione, ma il tuo codice ora è molto più flessibile, quindi se dovessi eseguire azioni diverse in base al valore di Question , puoi inserire la logica nella Question stessa (cioè nel modalità OO preferita) anziché mettere un sacco di istruzioni caso per tutto il codice per affrontare ogni scenario.

NB: rispondere aggiornato 2018-04-27 per utilizzare le funzionalità di C # 6; cioè espressioni di dichiarazione e definizioni del corpo di espressione lambda. Vedi la cronologia delle revisioni per il codice originale. Questo ha il vantaggio di rendere la definizione un po 'meno prolissa; che era stata una delle principali lamentele sull'approccio di questa risposta.


Di seguito è riportato il metodo di estensione

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

Basta lanciare l'enum, ad es

int something = (int) Question.Role;

Quanto sopra funzionerà per la maggior parte delle enumerazioni che si vedono in natura, poiché il tipo di base predefinito per un enum è int .

Tuttavia, come cecilphillip da cecilphillip , le enumerazioni possono avere diversi tipi di sottostanti. Se un enum è dichiarato come uint , long o ulong , dovrebbe essere gettato sul tipo di enum; ad esempio per

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

dovresti usare

long something = (long)StarsInMilkyWay.Wolf424B;

System.String è la classe di stringa .NET - in C # la string è un alias per System.String - così in uso sono gli stessi.

Per quanto riguarda le linee guida, non mi sento troppo impantanato e uso solo quello che vuoi - ci sono cose più importanti nella vita e il codice sarà lo stesso comunque.

Se vi trovate a costruire sistemi dove è necessario specificare la dimensione degli interi che state usando e quindi tendete a usare Int16 , Int32 , UInt16 , UInt32 ecc. Allora potrebbe sembrare più naturale usare String - e quando ci si muove tra diversi .net lingue potrebbe rendere le cose più comprensibili - altrimenti userei string e int.





c# enums casting int