Parse string to enum type

后端 未结 8 1166
灰色年华
灰色年华 2020-11-29 09:04

I have an enum type like this as an example:

public Enum MyEnum {
    enum1, enum2, enum3 };

I\'ll read a string from config file. What I n

相关标签:
8条回答
  • 2020-11-29 09:47
    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<T>(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<MyEnum>("Enum11"));
       Console.WriteLine(ParseEnum<MyEnum>("Enum1"));
       Console.WriteLine(ParseEnum<MyEnum>("Enum6").GetType());
       Console.WriteLine(ParseEnum<MyEnum>("Enum10"));
    }
    

    OUTPUT:

        //This line is empty as Enum11 is not there and function returns a null
    Enum1
    TestApp.Program+MyEnum
    Enum10
    Press any key to continue . . .
    
    0 讨论(0)
  • 2020-11-29 09:47

    If you're using .NET 3.5 (or even 2.0, if you trim out the extension method), I've had great luck with the techniques in this article:

    Enumerations and Strings - Stop the Madness!

    EDIT: Domain is gone and is now a link farm. I pulled the code (slightly modified and added to over time) from our codebase at work, which you can now find here:

    https://gist.github.com/1305566

    0 讨论(0)
  • 2020-11-29 09:49

    To return Enum by string, if contains:

        public static T GetEnum<T>(string s)
        {
            Array arr = Enum.GetValues(typeof(T));
            foreach (var x in arr)
            {
                if (x.ToString().Contains(s))
                    return (T)x;
            }
            return default(T);
        }
    
    0 讨论(0)
  • 2020-11-29 09:50

    You can use TryParse if you want to avoid using 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...
    

    I modified the selected answer a little bit. I hope you like it.

    public static class EnumUtils
    {
        public static Nullable<T> Parse<T>(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;
        }
    }
    
    0 讨论(0)
  • 2020-11-29 09:55

    What about something like:

    public static class EnumUtils
    {
        public static Nullable<T> Parse<T>(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;
        }
    }
    

    Used as:

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

    (Note: old version used try/catch around Enum.Parse)

    0 讨论(0)
  • 2020-11-29 09:57

    I have a TryParseName method in UnconstrainedMelody, a library for delegate and enum utility methods which uses "inexpressible" constraints via some postbuild trickery. (Code using the library doesn't need a postbuild, just to be clear.)

    You would use it like this:

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

    I don't currently have a case-insensitive version, but I could easily introduce one if you wanted. Note that this doesn't try to parse numbers e.g. "12" like the built-in version does, nor does it try to parse comma-separated lists of flags. I may add the flags version later on, but I can't see much point in the numeric version.

    This is done without boxing and without execution time type checking. Having the constraint is really handy :)

    Please let me know if you'd find a case-insensitive parse useful...

    0 讨论(0)
提交回复
热议问题