Home > Back-end >  Is it possible to cast to an Enum, when it is a Generic?
Is it possible to cast to an Enum, when it is a Generic?

Time:10-06

Trying to get a generic function like this to compile. The passed T is expected to be an Enum. Example is highly simplified :

    public T? GetEnumValue<T>(int id) where T: struct
    {
        // do some work to get the numerical value of the enum.
        // e.g. read number from a database, looking up by passed id. Fetched value could be null. 

        int? rawVal = 1;  

        // after work is done, return result as enum. 

        if (rawVal == null)
            return null; 
        
        return (T)rawVal.Value;  // Line XYZ : won't compile, as T is not an Enum at compile time.
    }

Example of use:

        SomeEnum? val = GetEnumValue<SomeEnum>(5);
        AnotherEnum? val2 = GetEnumValue<AnotherEnum>(3);

Where:

public enum SomeEnum 
{
    A,
    B,        
}

public enum AnotherEnum
{
    C,
    D,
}

Is there a workaround to get the line like that at XYZ to work?
This line is trying to convert the integral value of an enum, to an enum. Assume in this case that GetEnumValue will only be called where T is an Enum, which has underlying integer values.

EDIT: one possible workaround might be:

 return (T)Enum.ToObject(typeof(T), rawVal.Value);

, which seems to work.

CodePudding user response:

This will compile:

return (T)(object)rawVal.Value;

You ought to add the extra constraint too though:

where T : struct, Enum

EDIT:

I will leave my original answer below for completeness but, after testing, I see that what I expected work did not work. It was not possible to cast a non-null value as type T?, even though I expected it would be. This is option will work, but it's debatable whether it is an improvement on the original or not:

return rawVal.HasValue
           ? (T)(object)rawVal.Value
           : (T?)null;

ORIGINAL (Bad advice):

You should also be able to get rid of your existing null check and do this:

return (T?)((object)rawVal ?? null);

or this:

return (T?)(object)(rawVal ?? null);

This will compile:

return (T?)(object)rawVal;

but it does generate a warning. I haven't tested to see whether it actually would throw the warned InvalidCastException. I don't think it would but, if you don't like warnings in your code, the preceding options will avoid that.

CodePudding user response:

return (T?)Enum.Parse(typeof(T), rawVal.Value.ToString());

BTW, you can specify T to be Enum

public T? GetEnumValue<T>(int id) where T : Enum
{
   // ..
}
  • Related