Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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?

like image 415
Piotr Zierhoffer Avatar asked Oct 02 '22 17:10

Piotr Zierhoffer


1 Answers

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.

like image 179
Jon Skeet Avatar answered Oct 06 '22 00:10

Jon Skeet