How to convert an arbitrary object to enum?

I have an object. Usually it is either long or string, so to simplify the code let's assume just that.

I have to create a method that tries to convert this object to a provided enum. So:

public object ToEnum(Type enumType, object value)
{
    if(enumType.IsEnum)
    {
        if(Enum.IsDefined(enumType, value))
        {
           var val = Enum.Parse(enumType, (string)value);
           return val;
        }
    }
    return null;
}

With strings it works well. With numbers it causes problems, because a default underlying type for enum is int, not long and IsDefined throws an ArgumentException.

Of course I can do many checks, conversions or try-catches.

What I want is to have a clean and small code for that. Any ideas how to make it readable and simple?

Jon Skeet
people
quotationmark

It feels to me like you only actually want to handle three cases:

  • Input is already the right type
  • Strings
  • Integers in various types

I believe this will do what you want for valid input:

public object ToEnum(Type enumType, object value)
{
    if (value == null)
    {
        throw new ArgumentNullException("value");
    }
    if (enumType == null)
    {
        throw new ArgumentNullException("type");
    }
    if (!enumType.IsEnum)
    {
        return false;
    }
    string valueString = value as string;
    if (valueString != null)
    {
        return Enum.IsDefined(enumType, value) ? Enum.Parse(enumType, valueString) : null;
    }
    if (value.GetType() == enumType)
    {
        return value;
    }
    // This appears to handle longs etc
    return Enum.ToObject(enumType, value);
}

However, that will return a value of the right type even for undefined values. If you don't want that, change the last part to:

object candidate = Enum.ToObject(enumType, value);
return Enum.IsDefined(enumType, candidate) ? candidate : null;

Also, this will still throw an exception if you pass in a floating point number, or something like that. If you don't want that behaviour, you'll need to have a set of all the types you do want to accept, and check against that first.

people

See more on this question at Stackoverflow