Parse string a enum type

Ho un tipo enum come questo come esempio:

public Enum MyEnum { enum1, enum2, enum3 }; 

Leggerò una stringa dal file di configurazione. Cosa mi serve per analizzare la stringa in MyEnum o null o non definita. Non sono sicuro che i seguenti codici funzioneranno (mi dispiace di non avere accesso al mio VS adesso):

 // example: ParseEnum("ENUM1", ref eVal); bool ParseEnum(string value1, ref eVal) where T : Enum { bool bRet = false; var x = from x in Enum.GetNames(typeof(T)) where string.Equals(value1, x, StringComparison. OrdinalIgnoreCase) select x; if (x.Count() == 1 ) { eVal = Enum.Parse(typeof(T), x.Item(0)) as T; bRet = true; } return bRet; } 

Non sei sicuro se è corretto o c’è un altro modo semplice per analizzare una stringa sul valore MyEnum?

Che dire di qualcosa come:

 public static class EnumUtils { public static Nullable Parse(string input) where T : struct { //since we cant do a generic type constraint if (!typeof(T).IsEnum) { throw new ArgumentException("Generic Type 'T' must be an Enum"); } if (!string.IsNullOrEmpty(input)) { if (Enum.GetNames(typeof(T)).Any( e => e.Trim().ToUpperInvariant() == input.Trim().ToUpperInvariant())) { return (T)Enum.Parse(typeof(T), input, true); } } return null; } } 

Usato come:

 MyEnum? value = EnumUtils.Parse("foo"); 

(Nota: vecchia versione usata try/catch around Enum.Parse )

 private enum MyEnum { Enum1 = 1, Enum2 = 2, Enum3 = 3, Enum4 = 4, Enum5 = 5, Enum6 = 6, Enum7 = 7, Enum8 = 8, Enum9 = 9, Enum10 = 10 } private static Object ParseEnum(string s) { try { var o = Enum.Parse(typeof (T), s); return (T)o; } catch(ArgumentException) { return null; } } static void Main(string[] args) { Console.WriteLine(ParseEnum("Enum11")); Console.WriteLine(ParseEnum("Enum1")); Console.WriteLine(ParseEnum("Enum6").GetType()); Console.WriteLine(ParseEnum("Enum10")); } 

PRODUZIONE:

  //This line is empty as Enum11 is not there and function returns a null Enum1 TestApp.Program+MyEnum Enum10 Press any key to continue . . . 

Questa è una vecchia domanda, ma ora .NET 4.5 ha Enum.TryParse ().

http://msdn.microsoft.com/en-us/library/dd991317.aspx

Ho un metodo TryParseName in UnconstrainedMelody , una libreria per i metodi di utilità delegate ed enum che utilizza i vincoli “inesprimibili” tramite alcuni trucchi postbuild. (Il codice che utilizza la libreria non ha bisogno di un postbuild, tanto per essere chiari.)

Lo useresti in questo modo:

 Foo foo; bool parsed = Enums.TryParseName(name, out foo); 

Al momento non ho una versione insensibile alle maiuscole e minuscole, ma potrei facilmente introdurne una se volessi. Nota che questo non prova ad analizzare numeri come “12” come fa la versione built-in, né cerca di analizzare gli elenchi di flag separati da virgole. Potrei aggiungere la versione delle bandiere in seguito, ma non riesco a vedere molto nella versione numerica.

Questo viene fatto senza boxe e senza controllo del tempo di esecuzione. Avere il vincolo è davvero utile 🙂

Per favore fatemi sapere se troverete un parsing senza distinzione tra maiuscole e minuscole utile …

Ho appena combinato la syntax da qui , con la gestione delle eccezioni da qui , per creare questo:

 public static class Enum { public static T Parse(string value) { //Null check if(value == null) throw new ArgumentNullException("value"); //Empty string check value = value.Trim(); if(value.Length == 0) throw new ArgumentException("Must specify valid information for parsing in the string", "value"); //Not enum check Type t = typeof(T); if(!t.IsEnum) throw new ArgumentException("Type provided must be an Enum", "TEnum"); return (T)Enum.Parse(typeof(T), value); } } 

Potresti giocarci un po ‘per restituire null invece di lanciare eccezioni.

Se si utilizza .NET 3.5 (o anche 2.0, se si ritaglia il metodo di estensione), ho avuto molta fortuna con le tecniche in questo articolo:

Enumerations and Strings – Stop the Madness!

MODIFICA: il dominio non esiste più e ora è una farm di collegamento. Ho tirato il codice (leggermente modificato e aggiunto nel tempo) dalla nostra base di codice al lavoro, che ora puoi trovare qui:

https://gist.github.com/1305566

Puoi usare TryParse se vuoi evitare di usare try / catch.

 MyEnum eVal; if (Enum.TryParse("ENUM2", true, out eVal)){ // now eVal is the enumeration element: enum2 } //unable to parse. You can log the error, exit, redirect, etc... 

Ho modificato la risposta selezionata un po ‘. Spero vi piaccia.

 public static class EnumUtils { public static Nullable Parse(string input) where T : struct { //since we cant do a generic type constraint if (!typeof(T).IsEnum) { throw new ArgumentException("Generic Type 'T' must be an Enum"); } int intVal; if (!string.IsNullOrEmpty(input) && !int.TryParse(input, out intVal)) { T eVal; if (Enum.TryParse(input, true, out eVal)) { return eVal; } } return null; } } 

Per restituire Enum per stringa, se contiene:

  public static T GetEnum(string s) { Array arr = Enum.GetValues(typeof(T)); foreach (var x in arr) { if (x.ToString().Contains(s)) return (T)x; } return default(T); }