5

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!

Community
  • 1
  • 1
Richard
  • 3,207
  • 5
  • 30
  • 35
  • DO NOT DUPLICATE YOUR QUESTIONS!!! As it stands, your code is bogus. Please refer to your previous question, why I say that. – leppie Sep 28 '10 at 08:44
  • 1
    @leppie: Although the current code is bogus, the constraint part isn't - and it's a separate question. – Jon Skeet Sep 28 '10 at 08:46
  • @Jon Skeet: I believe firmly in sorting out one problem at a time. The way the OP is going, he will just get confused, and ultimately waste all of the time of the people trying to assist him. – leppie Sep 28 '10 at 08:49
  • @leppie: I suspect that if the OP goes forward with the suggestion in my answer, his code will actually become a lot simpler anyway - so the first problem will either go away or at least be easier to solve. – Jon Skeet Sep 28 '10 at 08:53
  • @leppie: As Jon Skeet says, this is a separate question, hence I decided not to put it together with the other question (to avoid confusion and enable other people to search for both). Even as you say the code does not work (which the other question addresses), the question is about the signature, and not the internals of the function, which still allows for the question I asked to be answered. – Richard Sep 28 '10 at 08:57
  • 2
    @leppie: It's 2 different questions. There's no rule that says you can't ask more than one question at a time, in fact, it's encouraged. If you think he's wasting your time I suggest you simply ignore the question. – Jaco Pretorius Sep 28 '10 at 09:12

2 Answers2

9

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.

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
1

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.

Bear Monkey
  • 513
  • 2
  • 9