Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Adding Constraints for Nullable Enum

I'm writing some Enum functionality, and have the following:

public static T ConvertStringToEnumValue<T>(string valueToConvert, bool isCaseSensitive)
{
    if (typeof(T).BaseType.FullName != "System.Enum" && typeof(T).BaseType.FullName != "System.ValueType")
    {
       throw new ArgumentException("Type must be of Enum and not " + typeof (T).BaseType.FullName);
    }

    if (String.IsNullOrWhiteSpace(valueToConvert))
      return (T)typeof(T).TypeInitializer.Invoke(null);

    valueToConvert = valueToConvert.Replace(" ", "");              

    if (typeof(T).BaseType.FullName == "System.ValueType")
    {
        return (T)Enum.Parse(Nullable.GetUnderlyingType(typeof(T)), valueToConvert, !isCaseSensitive);
    }

    return (T)Enum.Parse(typeof(T), valueToConvert, !isCaseSensitive);
}

I call it like this:

EnumHelper.ConvertStringToEnumValue<Enums.Animals?>("Cat");

I now want to add constraints to T to an Enum, such as (which I got from Stackoverflow article): where T : struct, IConvertible but I am having problems as T needs to be able to take nullable enums. Error message says:

The type 'Enums.Animals?' must be a non-nullable value type in order to use it as parameter 'T' in the generic type or method

Is there a way to do this, or do I need to just rely on the runtime checking which I have inside the method?

Thanks all!

like image 511
Richard Avatar asked Sep 28 '10 08:09

Richard


2 Answers

No, there's no constraint which says "T must be a value type, including nullable value types."

One option, however, would be to split the method into to:

public static T ConvertStringToEnumValue<T>(...) where T : struct
public static T? ConvertStringToNullableEnumValue<T>(...) where T : struct

Aside from anything else, each method's implementation would then be simpler, too.

Of course, we don't know how you're going to use this code - but if you're going to call it directly from non-generic methods, this would be my suggested approach.

Of course, that's still not going to stop someone from calling it with T=int or something like that... you might want to look at Unconstrained Melody for more rigid constraints.

like image 94
Jon Skeet Avatar answered Nov 11 '22 09:11

Jon Skeet


There is a trick that involves C++/CLI which does allow generic constraints on Enums. Write a base abstract class in C++/CLI with the Enum constraint. Reference the library in a C# project and implement the base class.

like image 43
Bear Monkey Avatar answered Nov 11 '22 08:11

Bear Monkey