Come lanciare int to enum?


Risposte:


3794

Da una stringa:

YourEnum foo = (YourEnum) Enum.Parse(typeof(YourEnum), yourString);

// The foo.ToString().Contains(",") check is necessary for enumerations marked with an [Flags] attribute
if (!Enum.IsDefined(typeof(YourEnum), foo) && !foo.ToString().Contains(","))
{
    throw new InvalidOperationException($"{yourString} is not an underlying value of the YourEnum enumeration.")
}

Da un int:

YourEnum foo = (YourEnum)yourInt;

Aggiornare:

Dal numero puoi anche

YourEnum foo = (YourEnum)Enum.ToObject(typeof(YourEnum) , yourInt);

31
@FlySwat, cosa succede se YourEnumè dinamico e sarà noto solo in fase di esecuzione, e quello che voglio è convertire in Enum?
Shimmy Weitzhandler,

226
Tieni presente che Enum.Parse NON funzionerà se il tuo codice è offuscato. In fase di esecuzione dopo l'offuscamento, la stringa viene confrontata con i nomi degli enum e, a questo punto, i nomi degli enum non sono come ci si aspetterebbe che fossero. Di conseguenza, l'analisi non riuscirà dove sono riusciti prima.
jropella,

158
ATTENZIONE Se usi la sintassi "da una stringa" sopra e passi una stringa non valida che è un numero (es. "2342342" - supponendo che non sia un valore del tuo enum), lo consentirà effettivamente senza generare un errore! Il tuo enum avrà quel valore (2342342) anche se non è una scelta valida nell'enum stesso.
JoeCool

132
Penso che questa risposta sia un po 'datata ora. Per la stringa, dovresti davvero utilizzare var result = Enum.TryParse(yourString, out yourEnum)oggigiorno (e controllare il risultato per determinare se la conversione non è riuscita).
Justin T Conroy,

20
È anche possibile non Enum.ParsetrueYourEnum foo = (YourEnum) Enum.Parse(typeof(YourEnum), yourString, true);
distinguere tra

900

Basta lanciarlo:

MyEnum e = (MyEnum)3;

Puoi verificare se è nell'intervallo usando Enum.IsDefined :

if (Enum.IsDefined(typeof(MyEnum), 3)) { ... }

218
Attenzione, non puoi usare Enum.IsDefined se usi l'attributo Flags e il valore è una combinazione di flag, ad esempio: Keys.L | Keys.Control
dtroy

15
Per quanto riguarda Enum.IsDefined, tieni presente che può essere pericoloso: msdn.microsoft.com/en-us/library/ms229025(VS.90).aspx
adrian,

3
Preferisco questa definizione: "Restituisce un'indicazione se esiste una costante con un valore specificato in un elenco specificato" da MSDN
Pap

3
... Perché la tua definizione può essere fuorviante, perché stai dicendo: "... controlla se è nell'intervallo ..." che implica in un intervallo di numeri con limiti di inizio e fine ...
Pap

3
@ mac9416 Ho provato a dare un esempio conciso su gist.github.com/alowdon/f7354cda97bac70b44e1c04bc0991bcc - fondamentalmente usando IsDefinedper controllare i valori di input, ti lasci vulnerabile alle persone che aggiungono nuovi valori di enum in seguito che passerebbero un IsDefinedcontrollo (dal momento che il nuovo esiste un valore nel nuovo codice), ma potrebbe non funzionare con il codice originale che hai scritto. È quindi più sicuro specificare esplicitamente i valori enum che il tuo codice è in grado di gestire.
Adriano,

238

In alternativa, utilizzare un metodo di estensione invece di una riga:

public static T ToEnum<T>(this string enumString)
{
    return (T) Enum.Parse(typeof (T), enumString);
}

Uso:

Color colorEnum = "Red".ToEnum<Color>();

O

string color = "Red";
var colorEnum = color.ToEnum<Color>();

7
Per l'elaborazione dell'input dell'utente, è probabilmente una buona idea chiamare il sovraccarico di Enum.Parse che consente di specificare che il confronto NON deve essere sensibile al maiuscolo / minuscolo (ovvero un utente che digita "rosso" (minuscolo) potrebbe bloccare il codice sopra senza questa modifica .)
BrainSlugs83

9
Comodo, ma la domanda si pone specificamente sugli ints.
Giuria

2
questo funziona anche se la stringa è un numero intero, ad es. "2"
TruthOf42

2
Ciò genererà un'eccezione se enumString è null (ha avuto un problema simile ieri). Prendi in considerazione l'utilizzo di TryParse anziché Parse. TryParse verificherà anche se T è un tipo Enum
Giustino il

Questo tipo di metodo di estensione System.Stringsembra inquinamento dello spazio dei nomi
Mr Anderson,

160

Penso che per ottenere una risposta completa, le persone devono sapere come funzionano gli enum internamente in .NET.

Come funzionano le cose

Un enum in .NET è una struttura che mappa un set di valori (campi) su un tipo base (il valore predefinito è int). Tuttavia, puoi effettivamente scegliere il tipo integrale a cui l'enum è associato:

public enum Foo : short

In questo caso, l'enum è mappato sul shorttipo di dati, il che significa che verrà archiviato in memoria come short e si comporterà come short quando lo lanci e lo usi.

Se lo guardi da un punto di vista di IL, un enum (normale, int) si presenta così:

.class public auto ansi serializable sealed BarFlag extends System.Enum
{
    .custom instance void System.FlagsAttribute::.ctor()
    .custom instance void ComVisibleAttribute::.ctor(bool) = { bool(true) }

    .field public static literal valuetype BarFlag AllFlags = int32(0x3fff)
    .field public static literal valuetype BarFlag Foo1 = int32(1)
    .field public static literal valuetype BarFlag Foo2 = int32(0x2000)

    // and so on for all flags or enum values

    .field public specialname rtspecialname int32 value__
}

Ciò che dovrebbe attirare la tua attenzione qui è che value__è memorizzato separatamente dai valori enum. Nel caso dell'enum Foosopra, il tipo di value__è int16. Questo in pratica significa che puoi archiviare quello che vuoi in un enum, purché i tipi corrispondano .

A questo punto vorrei sottolineare che si System.Enumtratta di un tipo di valore, il che significa sostanzialmente che BarFlagoccuperà 4 byte in memoria e ne Foooccuperà 2, ad esempio la dimensione del tipo sottostante (in realtà è più complicato di così, ma Hey...).

La risposta

Quindi, se si dispone di un numero intero che si desidera associare a un enum, il runtime deve solo fare 2 cose: copiare i 4 byte e nominarlo con qualcos'altro (il nome dell'enum). La copia è implicita perché i dati sono archiviati come tipo di valore: ciò significa sostanzialmente che se si utilizza un codice non gestito, è possibile scambiare semplicemente enumerazioni e numeri interi senza copiare i dati.

Per renderlo sicuro, penso che sia una buona pratica sapere che i tipi sottostanti sono gli stessi o implicitamente convertibili e per garantire che i valori enum esistano (non sono controllati per impostazione predefinita!).

Per vedere come funziona, prova il seguente codice:

public enum MyEnum : int
{
    Foo = 1,
    Bar = 2,
    Mek = 5
}

static void Main(string[] args)
{
    var e1 = (MyEnum)5;
    var e2 = (MyEnum)6;

    Console.WriteLine("{0} {1}", e1, e2);
    Console.ReadLine();
}

Nota che anche il casting e2funziona! Dal punto di vista del compilatore sopra questo ha senso: il value__campo è semplicemente riempito con 5 o 6 e quando le Console.WriteLinechiamate ToString(), il nome di e1viene risolto mentre il nome di e2non lo è.

Se non è quello che intendevi, usa Enum.IsDefined(typeof(MyEnum), 6)per verificare se il valore che stai lanciando viene mappato su un enum definito.

Nota anche che sono esplicito sul tipo di base dell'enum, anche se il compilatore lo controlla. Lo sto facendo per assicurarmi di non incappare in sorprese lungo la strada. Per vedere queste sorprese in azione, puoi usare il seguente codice (in realtà ho visto che ciò accade molto nel codice del database):

public enum MyEnum : short
{
    Mek = 5
}

static void Main(string[] args)
{
    var e1 = (MyEnum)32769; // will not compile, out of bounds for a short

    object o = 5;
    var e2 = (MyEnum)o;     // will throw at runtime, because o is of type int

    Console.WriteLine("{0} {1}", e1, e2);
    Console.ReadLine();
}

7
Mi rendo conto che questo è un vecchio post, ma come si ottiene questo livello di conoscenza in c #? È dalla lettura delle specifiche C #?
Rolan,

20
@Rolan A volte vorrei che più persone lo chiedessero. :-) A dire il vero non lo so davvero; Cerco di capire come funzionano le cose e ottenere informazioni ovunque io riesca a trovarle. Ho letto lo standard C #, ma decompongo regolarmente anche il codice con Reflector (guardo anche molto il codice dell'assemblatore x86) e faccio tonnellate di piccoli esperimenti. Inoltre, conoscere altre lingue aiuta in questo caso; Faccio CS da circa 30 anni, e ad un certo punto alcune cose diventano "logiche" - f.ex. un enum dovrebbe essere di tipo integrale, perché altrimenti l'interoperabilità si interromperà (o la tua performance andrà in rovina).
atlaste,

9
Credo che la chiave per eseguire correttamente l'ingegneria del software sia sapere come funzionano le cose. Per me ciò significa che se scrivi un pezzo di codice, sai come si traduce approssimativamente in f.ex. operazioni del processore e recupero / scrittura della memoria. Se chiedi come arrivare a quel livello, suggerirei di costruire una tonnellata di piccoli casi di test, rendendoli più difficili man mano che procedi, provando a prevederne ogni volta l'esito e testandoli in seguito (incl. Decompilazione, ecc.). Dopo aver capito tutti i dettagli e tutte le caratteristiche, puoi verificare se hai capito bene nello standard (noioso). Almeno, questo sarebbe il mio approccio.
atlaste,

1
Risposta fantastica, grazie! Nell'ultimo esempio di codice, genera un'eccezione in fase di esecuzione poiché o è un oggetto. È possibile eseguire il cast di una variabile int in un breve purché rientri nel breve intervallo.
gravid

@gravidThoughts Grazie. In realtà è un'operazione di unboxing, quindi non farà conversioni implicite come quelle che descrivi. Il casting a volte è fonte di confusione in C # se non si conoscono i dettagli ... Comunque, perché int! = short, Verrà lanciato (unboxing fallisce). Se lo fai object o = (short)5;, funzionerà, perché i tipi corrisponderanno. Non si tratta della gamma, è davvero del tipo.
atlaste


64

Sto usando questo pezzo di codice per lanciare int nel mio enum:

if (typeof(YourEnum).IsEnumDefined(valueToCast)) return (YourEnum)valueToCast;
else { //handle it here, if its not defined }

La trovo la soluzione migliore.


1
questo è buono. sono stato sorpreso che non ci sia un'eccezione quando si lancia un valore non valido in un enum supportato da int.
Orion Elenzil,

Questo in realtà non è così diverso dalla risposta più votata. Quella risposta discute anche sull'uso di Enum.IsDefined dopo aver eseguito il cast della stringa nel tipo Enum. Quindi, anche se la stringa è stata lanciata senza errori, Enum.IsDefined la catturerà comunque
Don Cheadle il

53

Di seguito è una bella classe di utilità per Enums

public static class EnumHelper
{
    public static int[] ToIntArray<T>(T[] value)
    {
        int[] result = new int[value.Length];
        for (int i = 0; i < value.Length; i++)
            result[i] = Convert.ToInt32(value[i]);
        return result;
    }

    public static T[] FromIntArray<T>(int[] value) 
    {
        T[] result = new T[value.Length];
        for (int i = 0; i < value.Length; i++)
            result[i] = (T)Enum.ToObject(typeof(T),value[i]);
        return result;
    }


    internal static T Parse<T>(string value, T defaultValue)
    {
        if (Enum.IsDefined(typeof(T), value))
            return (T) Enum.Parse(typeof (T), value);

        int num;
        if(int.TryParse(value,out num))
        {
            if (Enum.IsDefined(typeof(T), num))
                return (T)Enum.ToObject(typeof(T), num);
        }

        return defaultValue;
    }
}

47

Per i valori numerici, questo è più sicuro in quanto restituirà un oggetto qualunque cosa:

public static class EnumEx
{
    static public bool TryConvert<T>(int value, out T result)
    {
        result = default(T);
        bool success = Enum.IsDefined(typeof(T), value);
        if (success)
        {
            result = (T)Enum.ToObject(typeof(T), value);
        }
        return success;
    }
}

Non funziona per le bandiere
Seyed Morteza Mousavi il


35

Se si dispone di un numero intero che funge da maschera di bit e potrebbe rappresentare uno o più valori in un elenco [Flags], è possibile utilizzare questo codice per analizzare i singoli valori di flag in un elenco:

for (var flagIterator = 0; flagIterator < 32; flagIterator++)
{
    // Determine the bit value (1,2,4,...,Int32.MinValue)
    int bitValue = 1 << flagIterator;

    // Check to see if the current flag exists in the bit mask
    if ((intValue & bitValue) != 0)
    {
        // If the current flag exists in the enumeration, then we can add that value to the list
        // if the enumeration has that flag defined
        if (Enum.IsDefined(typeof(MyEnum), bitValue))
            Console.WriteLine((MyEnum)bitValue);
    }
}

Si noti che ciò presuppone che il tipo sottostante di enumsia un numero intero a 32 bit con segno. Se fosse un diverso tipo numerico, dovresti cambiare i 32 hardcoded per riflettere i bit in quel tipo (o derivarlo programmaticamente usando Enum.GetUnderlyingType())


1
Questo loop non termina mai? flagIterator = 0x00000001, flagIterator = 0x00000002, flagIterator = 0x00000004, ..., flagIterator = 0x40000000, flagIterator = 0x80000000, flagIterator = 0x00000000. In altre parole, il valore sarà sempre inferiore a 0x80000000 perché trabocca a zero dopo il caso in cui il bit D31 = 1. Quindi, rimane 0 per sempre perché spostando a sinistra il valore 0 dà 0
Christian Gingras

Grande cattura @christiangingras, grazie! Ho modificato la risposta per tenerne conto, e dovrei tener conto quando viene impostato il bit più alto (ovvero 0x80000000 / Int32.MinValue)
Evan M

27

A volte hai un oggetto per il MyEnumtipo. Piace

var MyEnumType = typeof(MyEnumType);

Poi:

Enum.ToObject(typeof(MyEnum), 3)

26

Questo è un metodo di conversione sicuro consapevole dell'enumerazione di flag:

public static bool TryConvertToEnum<T>(this int instance, out T result)
  where T: Enum
{
  var enumType = typeof (T);
  var success = Enum.IsDefined(enumType, instance);
  if (success)
  {
    result = (T)Enum.ToObject(enumType, instance);
  }
  else
  {
    result = default(T);
  }
  return success;
}

3
Questo può ora essere migliorato con C # 7.3 vincolando Enuminvece di struct, il che significa che non dobbiamo fare affidamento sul controllo di runtime!
Scott,

20

inserisci qui la descrizione dell'immagine

Per convertire una stringa in ENUM o int in costante ENUM dobbiamo usare la funzione Enum.Parse. Ecco un video di YouTube https://www.youtube.com/watch?v=4nhx4VwdRDk che in realtà dimostra di avere una stringa e lo stesso vale per int.

Il codice va come mostrato sotto dove "rosso" è la stringa e "MyColors" è il colore ENUM che ha le costanti di colore.

MyColors EnumColors = (MyColors)Enum.Parse(typeof(MyColors), "Red");

20

Allontanandosi leggermente dalla domanda originale, ma ho trovato utile una risposta alla domanda Stack Overflow Ottieni valore int da enum . Crea una classe statica con public const intproprietà, che ti consenta di raccogliere facilmente un insieme di intcostanti correlate e di non doverle lanciare intquando le usi.

public static class Question
{
    public static readonly int Role = 2;
    public static readonly int ProjectFunding = 3;
    public static readonly int TotalEmployee = 4;
    public static readonly int NumberOfServers = 5;
    public static readonly int TopBusinessConcern = 6;
}

Ovviamente, alcune funzionalità del tipo enum andranno perse, ma per l'archiviazione di un gruppo di costanti ID database, sembra una soluzione piuttosto ordinata.


5
enum ha sostituito l'uso di costanti intere come questa in quanto forniscono una maggiore sicurezza del tipo
Paul Richards,

1
Paul, questo è un metodo per raccogliere insieme costanti int correlate (es. Costanti ID database) in modo che possano essere usate direttamente senza doverle lanciare in int ogni volta che vengono usate. Il loro tipo è intero, non ad esempio DatabaseIdsEnum.
Ted,

1
C'è almeno una situazione che ho riscontrato in cui la sicurezza del tipo enum può essere aggirata involontariamente.
Thierry,

Ma gli enum si assicurano anche che i valori siano tutti unici, qualcosa che manca anche a questo approccio
derHugo,

15

Questo analizza numeri interi o stringhe in un enum target con una corrispondenza parziale in dot.NET 4.0 usando generici come nella classe di utilità Tawani sopra. Lo sto usando per convertire le variabili di switch della riga di comando che possono essere incomplete. Poiché un enum non può essere nullo, è necessario fornire logicamente un valore predefinito. Può essere chiamato così:

var result = EnumParser<MyEnum>.Parse(valueToParse, MyEnum.FirstValue);

Ecco il codice:

using System;

public class EnumParser<T> where T : struct
{
    public static T Parse(int toParse, T defaultVal)
    {
        return Parse(toParse + "", defaultVal);
    }
    public static T Parse(string toParse, T defaultVal) 
    {
        T enumVal = defaultVal;
        if (defaultVal is Enum && !String.IsNullOrEmpty(toParse))
        {
            int index;
            if (int.TryParse(toParse, out index))
            {
                Enum.TryParse(index + "", out enumVal);
            }
            else
            {
                if (!Enum.TryParse<T>(toParse + "", true, out enumVal))
                {
                    MatchPartialName(toParse, ref enumVal);
                }
            }
        }
        return enumVal;
    }

    public static void MatchPartialName(string toParse, ref T enumVal)
    {
        foreach (string member in enumVal.GetType().GetEnumNames())
        {
            if (member.ToLower().Contains(toParse.ToLower()))
            {
                if (Enum.TryParse<T>(member + "", out enumVal))
                {
                    break;
                }
            }
        }
    }
}

Cordiali saluti: La domanda era sugli interi, che nessuno menzionato convertirà esplicitamente anche in Enum.TryParse ()


13

Da una stringa: (Enum.Parse non è aggiornato, usa Enum.TryParse)

enum Importance
{}

Importance importance;

if (Enum.TryParse(value, out importance))
{
}

4
La domanda si pone specificamente sugli interi.
Giuria

4
Will Yu Modifica la tua risposta a far sapere a tutti Enum.TryParse lavorerà su una stringa del valore o il nome del enum (non ho potuto resistere)
JeremyWeir

1
Jeremy, Weir ci sta lavorando (non ha resistito neanche).
huysentruitw,

11

Di seguito è un metodo di estensione leggermente migliore

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

10

Nel mio caso, avevo bisogno di restituire l'enum da un servizio WCF. Avevo anche bisogno di un nome descrittivo, non solo di enum.ToString ().

Ecco la mia classe WCF.

[DataContract]
public class EnumMember
{
    [DataMember]
    public string Description { get; set; }

    [DataMember]
    public int Value { get; set; }

    public static List<EnumMember> ConvertToList<T>()
    {
        Type type = typeof(T);

        if (!type.IsEnum)
        {
            throw new ArgumentException("T must be of type enumeration.");
        }

        var members = new List<EnumMember>();

        foreach (string item in System.Enum.GetNames(type))
        {
            var enumType = System.Enum.Parse(type, item);

            members.Add(
                new EnumMember() { Description = enumType.GetDescriptionValue(), Value = ((IConvertible)enumType).ToInt32(null) });
        }

        return members;
    }
}

Ecco il metodo di estensione che ottiene la descrizione dall'enum.

    public static string GetDescriptionValue<T>(this T source)
    {
        FieldInfo fileInfo = source.GetType().GetField(source.ToString());
        DescriptionAttribute[] attributes = (DescriptionAttribute[])fileInfo.GetCustomAttributes(typeof(DescriptionAttribute), false);            

        if (attributes != null && attributes.Length > 0)
        {
            return attributes[0].Description;
        }
        else
        {
            return source.ToString();
        }
    }

Implementazione:

return EnumMember.ConvertToList<YourType>();

9

Non so più dove ottengo la parte di questa estensione enum, ma proviene da StackOverflow. Mi dispiace per questo! Ma ho preso questo e l'ho modificato per enumerazioni con Flags. Per gli enum con Flags ho fatto questo:

  public static class Enum<T> where T : struct
  {
     private static readonly IEnumerable<T> All = Enum.GetValues(typeof (T)).Cast<T>();
     private static readonly Dictionary<int, T> Values = All.ToDictionary(k => Convert.ToInt32(k));

     public static T? CastOrNull(int value)
     {
        T foundValue;
        if (Values.TryGetValue(value, out foundValue))
        {
           return foundValue;
        }

        // For enums with Flags-Attribut.
        try
        {
           bool isFlag = typeof(T).GetCustomAttributes(typeof(FlagsAttribute), false).Length > 0;
           if (isFlag)
           {
              int existingIntValue = 0;

              foreach (T t in Enum.GetValues(typeof(T)))
              {
                 if ((value & Convert.ToInt32(t)) > 0)
                 {
                    existingIntValue |= Convert.ToInt32(t);
                 }
              }
              if (existingIntValue == 0)
              {
                 return null;
              }

              return (T)(Enum.Parse(typeof(T), existingIntValue.ToString(), true));
           }
        }
        catch (Exception)
        {
           return null;
        }
        return null;
     }
  }

Esempio:

[Flags]
public enum PetType
{
  None = 0, Dog = 1, Cat = 2, Fish = 4, Bird = 8, Reptile = 16, Other = 32
};

integer values 
1=Dog;
13= Dog | Fish | Bird;
96= Other;
128= Null;

9

Dovresti integrare un certo tipo di rilassamento per essere più robusto.

public static T ToEnum<T>(dynamic value)
{
    if (value == null)
    {
        // default value of an enum is the object that corresponds to
        // the default value of its underlying type
        // https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/default-values-table
        value = Activator.CreateInstance(Enum.GetUnderlyingType(typeof(T)));
    }
    else if (value is string name)
    {
        return (T)Enum.Parse(typeof(T), name);
    }

    return (T)Enum.ToObject(typeof(T),
             Convert.ChangeType(value, Enum.GetUnderlyingType(typeof(T))));
}

Test Case

[Flags]
public enum A : uint
{
    None  = 0, 
    X     = 1 < 0,
    Y     = 1 < 1
}

static void Main(string[] args)
{
    var value = EnumHelper.ToEnum<A>(7m);
    var x = value.HasFlag(A.X); // true
    var y = value.HasFlag(A.Y); // true

    var value2 = EnumHelper.ToEnum<A>("X");

    var value3 = EnumHelper.ToEnum<A>(null);

    Console.ReadKey();
}

Questa è una bella risposta È un peccato che sia così in fondo alla pagina al momento!
MikeBeaton,

8

Diversi modi per lanciare da e verso Enum

enum orientation : byte
{
 north = 1,
 south = 2,
 east = 3,
 west = 4
}

class Program
{
  static void Main(string[] args)
  {
    orientation myDirection = orientation.north;
    Console.WriteLine(“myDirection = {0}”, myDirection); //output myDirection =north
    Console.WriteLine((byte)myDirection); //output 1

    string strDir = Convert.ToString(myDirection);
        Console.WriteLine(strDir); //output north

    string myString = north”; //to convert string to Enum
    myDirection = (orientation)Enum.Parse(typeof(orientation),myString);


 }
}

8

Può aiutarti a convertire qualsiasi dato di input nell'enum desiderato dall'utente . Supponiamo di avere un enum come sotto che di default int . Aggiungi un valore predefinito all'inizio del tuo enum. Che viene utilizzato nel medthod degli helper quando non viene trovata alcuna corrispondenza con il valore di input.

public enum FriendType  
{
    Default,
    Audio,
    Video,
    Image
}

public static class EnumHelper<T>
{
    public static T ConvertToEnum(dynamic value)
    {
        var result = default(T);
        var tempType = 0;

        //see Note below
        if (value != null &&
            int.TryParse(value.ToString(), out  tempType) && 
            Enum.IsDefined(typeof(T), tempType))
        {
            result = (T)Enum.ToObject(typeof(T), tempType); 
        }
        return result;
    }
}

NB: Qui provo ad analizzare il valore in int, perché enum è di default int Se si definisce enum in questo modo, che è di tipo byte .

public enum MediaType : byte
{
    Default,
    Audio,
    Video,
    Image
} 

È necessario modificare l'analisi dal metodo helper da

int.TryParse(value.ToString(), out  tempType)

per

byte.TryParse(value.ToString(), out tempType)

Controllo il mio metodo per i seguenti input

EnumHelper<FriendType>.ConvertToEnum(null);
EnumHelper<FriendType>.ConvertToEnum("");
EnumHelper<FriendType>.ConvertToEnum("-1");
EnumHelper<FriendType>.ConvertToEnum("6");
EnumHelper<FriendType>.ConvertToEnum("");
EnumHelper<FriendType>.ConvertToEnum("2");
EnumHelper<FriendType>.ConvertToEnum(-1);
EnumHelper<FriendType>.ConvertToEnum(0);
EnumHelper<FriendType>.ConvertToEnum(1);
EnumHelper<FriendType>.ConvertToEnum(9);

mi scusi per il mio inglese


8

Ecco un metodo di estensione che getta Int32a Enum.

Rispetta i flag bit a bit anche quando il valore è superiore al massimo possibile. Per esempio se hai un enum con possibilità 1 , 2 e 4 , ma int è 9 , capisce che come 1 in assenza di un 8 . Ciò consente di effettuare aggiornamenti dei dati prima degli aggiornamenti del codice.

   public static TEnum ToEnum<TEnum>(this int val) where TEnum : struct, IComparable, IFormattable, IConvertible
    {
        if (!typeof(TEnum).IsEnum)
        {
            return default(TEnum);
        }

        if (Enum.IsDefined(typeof(TEnum), val))
        {//if a straightforward single value, return that
            return (TEnum)Enum.ToObject(typeof(TEnum), val);
        }

        var candidates = Enum
            .GetValues(typeof(TEnum))
            .Cast<int>()
            .ToList();

        var isBitwise = candidates
            .Select((n, i) => {
                if (i < 2) return n == 0 || n == 1;
                return n / 2 == candidates[i - 1];
            })
            .All(y => y);

        var maxPossible = candidates.Sum();

        if (
            Enum.TryParse(val.ToString(), out TEnum asEnum)
            && (val <= maxPossible || !isBitwise)
        ){//if it can be parsed as a bitwise enum with multiple flags,
          //or is not bitwise, return the result of TryParse
            return asEnum;
        }

        //If the value is higher than all possible combinations,
        //remove the high imaginary values not accounted for in the enum
        var excess = Enumerable
            .Range(0, 32)
            .Select(n => (int)Math.Pow(2, n))
            .Where(n => n <= val && n > 0 && !candidates.Contains(n))
            .Sum();

        return Enum.TryParse((val - excess).ToString(), out asEnum) ? asEnum : default(TEnum);
    }

6

il modo semplice e chiaro per lanciare un int da enumerare in c #:

 public class Program
    {
        public enum Color : int
        {
            Blue = 0,
            Black = 1,
            Green = 2,
            Gray = 3,
            Yellow =4
        }

        public static void Main(string[] args)
        {
            //from string
            Console.WriteLine((Color) Enum.Parse(typeof(Color), "Green"));

            //from int
            Console.WriteLine((Color)2);

            //From number you can also
            Console.WriteLine((Color)Enum.ToObject(typeof(Color) ,2));
        }
    }

6

È sufficiente utilizzare la conversione esplicita Cast int per enum o enum in int

class Program
{
    static void Main(string[] args)
    {
        Console.WriteLine((int)Number.three); //Output=3

        Console.WriteLine((Number)3);// Outout three
        Console.Read();
    }

    public enum Number
    {
        Zero = 0,
        One = 1,
        Two = 2,
        three = 3
    }
}

4
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;

namespace SamplePrograme
{
    public class Program
    {
        public enum Suit : int
        {
            Spades = 0,
            Hearts = 1,
            Clubs = 2,
            Diamonds = 3
        }

        public static void Main(string[] args)
        {
            //from string
            Console.WriteLine((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));
        }
    }
}

3

Fai proprio come di seguito:

int intToCast = 1;
TargetEnum f = (TargetEnum) intToCast ;

Per assicurarti di lanciare solo i valori giusti e che puoi generare un'eccezione altrimenti:

int intToCast = 1;
if (Enum.IsDefined(typeof(TargetEnum), intToCast ))
{
    TargetEnum target = (TargetEnum)intToCast ;
}
else
{
   // Throw your exception.
}

Si noti che l'utilizzo di IsDefined è costoso e persino più del semplice casting, quindi dipende dalla propria implementazione decidere di usarlo o meno.


3

È possibile utilizzare il metodo di estensione.

public static class Extensions
{

    public static T ToEnum<T>(this string data) where T : struct
    {
        if (!Enum.TryParse(data, true, out T enumVariable))
        {
            if (Enum.IsDefined(typeof(T), enumVariable))
            {
                return enumVariable;
            }
        }

        return default;
    }

    public static T ToEnum<T>(this int data) where T : struct
    {
        return (T)Enum.ToObject(typeof(T), data);
    }
}

usare come il codice qui sotto

enum:

public enum DaysOfWeeks
{
    Monday = 1,
    Tuesday = 2,
    Wednesday = 3,
    Thursday = 4,
    Friday = 5,
    Saturday = 6,
    Sunday = 7,
}

Utilizzo:

 string Monday = "Mon";
 int Wednesday = 3;
 var Mon = Monday.ToEnum<DaysOfWeeks>();
 var Wed = Wednesday.ToEnum<DaysOfWeeks>();
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.