views:

202

answers:

2

I have the following methods in an enum helper class (I have simplified it for the purpose of the question):

static class EnumHelper
{
    public enum EnumType1 : int
    {
        Unknown = 0,
        Yes = 1,
        No = 2
    }

    public enum EnumType2 : int
    {
        Unknown = 0,
        Dog = 1,
        Cat = 2,
        Bird = 3
    }

    public enum EnumType3
    {
        Unknown,
        iPhone,
        Andriod,
        WindowsPhone7,
        Palm
    }

    public static EnumType1 ConvertToEnumType1(string value)
    {
        return (string.IsNullOrEmpty(value)) ?
            EnumType1.Unknown :
            (EnumType1)(Enum.Parse(typeof(EnumType1), value, true));
    }

    public static EnumType2 ConvertToEnumType2(string value)
    {
        return (string.IsNullOrEmpty(value)) ?
            EnumType2.Unknown :
            (EnumType2)(Enum.Parse(typeof(EnumType2), value, true));
    }

    public static EnumType3 ConvertToEnumType3(string value)
    {
        return (string.IsNullOrEmpty(value)) ?
            EnumType3.Unknown :
            (EnumType3)(Enum.Parse(typeof(EnumType3), value, true));
    }
}

So the question here is, can I trim this down to an Enum extension method or maybe some type of single method that can handle any type. I have found some examples to do so with basic enums but the difference in my example is all the enums have the Unknown item that I need returned if the string is null or empty (if no match is found I want it to fail).

Looking for something like the following maybe:

EnumType1 value = EnumType1.Convert("Yes");
// or
EnumType1 value = EnumHelper.Convert(EnumType1, "Yes");

One function to do it all... how to handle the Unknown element is the part that I am hung up on.

Edit: Adjusted one of the enums to not be defined with integers. So I can guarantee that 0 will always be the case but Unknown will always be the correct text... I guess I could use the same example as the T(0) but do another parse on the text "Unknown".

+2  A: 

use generics... something like this....

public static TResult ConvertTo<TResult>( this string source )
{
     if( !typeof(TResult).IsEnum )
     {
         throw new NotSupportedException( "TResult must be an Enum" );
     }

    if (!Enum.GetNames(typeof(TResult)).Contains(source))
        return default(TResult);


     return (TResult)Enum.Parse( typeof(TResult), source );
}

(the code came from here)

Muad'Dib
This I knew how to do...but how will I get the `EnumTypeX.Unknown` back when it is null or empty?
Kelsey
add this line... if (!Enum.GetNames(typeof(TResult)).Contains(source)) return default(TResult);
Muad'Dib
+4  A: 

Use this, assuming that Unknown is always the 0 value.

public static T ConvertToEnum<T>(this string value) where T : new()
{
    if( !typeof(T).IsEnum )
        throw new NotSupportedException( "T must be an Enum" );

    try
    {
        return (T)Enum.Parse(typeof(T), value);
    }
    catch
    {
        return default(T); // equivalent to (T)0
        //return (T)Enum.Parse(typeof(T), "Unknown"));
    }
}

Usage:

EnumType2 a = "Cat".ConvertToEnum<EnumType2>(); 
EnumType2 b = "Person".ConvertToEnum<EnumType2>(); // Unknown

EDIT By OP (Kelsey): Your answer lead me to the correct answer so I thought I would include it here:

public static T ConvertTo<T>(this string value)
{
    T returnValue = (T)(Enum.Parse(typeof(T), "Unknown", true));
    if ((string.IsNullOrEmpty(value) == false) && 
        (typeof(T).IsEnum))
    {
        try { returnValue = (T)(Enum.Parse(typeof(T), value, true)); }
        catch { }
    }
    return returnValue;
}
chilltemp
Constraint cannot be special class 'System.Enum'
Muad'Dib
@Maud'Dib: Ugh, you're right. I didn't see the error in my dummy project. I'll update.
chilltemp
@Kelsey: Your right, you can simply reparse 'Unknown' each time, but casting from 0 is more efficient assuming that it's safe for your Enums.
chilltemp
`(T)0` does not compile: "Cannot convert type 'int' to 'T'"
dtb
Thanks, I have editted into your answer what I will end up using since your answer helped me get there.
Kelsey