index - Trasmetti int enum in C#




get enum from string (14)

A volte hai un oggetto al tipo MyEnum . Piace

var MyEnumType = typeof(MyEnumType);

Poi:

Enum.ToObject(typeof(MyEnum), 3)

https://code.i-harness.com

Come si può lanciare un int a un enum in C #?


Basta lanciarlo:

MyEnum e = (MyEnum)3;

È possibile verificare se è nell'intervallo utilizzando Enum.IsDefined . È Enum.IsDefined :

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

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

Di seguito è riportata una buona 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;
    }
}

Diversi modi di 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);


 }
}

In alternativa, usa un metodo di estensione invece di una linea singola:

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

Non so più dove ottengo la parte di questa estensione enum, ma è da . Mi dispiace per questo! Ma ho preso questo e l'ho modificato per enumerare con Flags. Per enumerare con le bandiere, 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;

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

Come funzionano le cose

Un enum in .NET è una struttura che mappa un insieme di valori (campi) in un tipo di base (il valore predefinito è int ). Tuttavia, puoi effettivamente scegliere il tipo integrale che il tuo enum esegue su:

public enum Foo : short

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

Se lo guardi da un punto di vista di IL, un enum (normale, int) assomiglia a questo:

.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 vostra attenzione qui è che il value__ è memorizzato separatamente dai valori enum. Nel caso dell'enum Foo sopra, il tipo di valore value__ è int16. Ciò significa fondamentalmente che è possibile memorizzare ciò che si desidera in una enumerazione, purché i tipi corrispondano .

A questo punto vorrei sottolineare che System.Enum è un tipo di valore, che in pratica significa che BarFlag occuperà 4 byte in memoria e che Foo occuperà 2 - ad esempio la dimensione del tipo sottostante (in realtà è più complicato di così, ma hey ...).

La risposta

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

Per renderlo sicuro, penso che sia una buona pratica sapere che i tipi sottostanti sono uguali o implicitamente convertibili e garantire che i valori enum esistano (non sono controllati di default!).

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 casting in e2 funziona! Dal punto di vista del compilatore sopra questo ha senso: il campo value__ viene semplicemente riempito con 5 o 6 e quando Console.WriteLine chiama ToString() , il nome di e1 viene risolto mentre il nome di e2 non lo è.

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

Si noti inoltre che sono esplicito sul tipo sottostante dell'enumerazione, anche se il compilatore lo controlla effettivamente. Lo sto facendo per assicurarmi di non avere sorprese lungo la strada. Per vedere queste sorprese in azione, puoi usare il seguente codice (in realtà ho visto accadere molte cose 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();
}

Prendi il seguente esempio:

int one = 1;
MyEnum e = (MyEnum)one;

Può aiutarti a convertire qualsiasi dato di input nell'enum desiderato dall'utente. Supponiamo di avere una enumerazione come di seguito che per impostazione predefinita int . Aggiungi un valore predefinito all'inizio del tuo enum. Che viene utilizzato dagli assistenti se non è stata 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 cerco di analizzare il valore in int, perché enum è di default int Se si definisce enum come questo che è il tipo di byte .

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

È necessario modificare l'analisi dal metodo di supporto da

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

a

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


Questo analizza interi o stringhe a un enum di destinazione con corrispondenza parziale in dot.NET 4.0 usando generici come nella classe di utilità di Tawani sopra. Lo sto usando per convertire variabili di switch da riga di comando che potrebbero 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;
                }
            }
        }
    }
}

A proposito: la domanda riguardava i numeri interi, che nessuno menzionava anche in modo esplicito in Enum.TryParse ()



Sto usando questo pezzo di codice per trasmettere int al mio enum:

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

La trovo la soluzione migliore.


Un po 'di distanza dalla domanda originale, ma ho trovato una risposta alla domanda Ottieni un valore int da enum utile. Crea una classe statica con public const int proprietà public const int , che ti consentono di raccogliere facilmente un gruppo di costanti int correlate e di non doverle int a int quando le utilizzi.

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 delle funzionalità di tipo enum andranno perse, ma per la memorizzazione di una serie di costanti ID del database, sembra una soluzione piuttosto ordinata.







casting