Search code examples
c#genericsenumsicomparablet

C# boxing enum error with generics


I don't understand what is going on here...

I've got the following error: The type 'TestApp.TestVal' cannot be used as type parameter 'T' in the generic type or method 'TestApp.SomeClass<T>'. There is no boxing conversion from 'TestApp.TestVal' to 'System.IComparable<TestApp.TestVal>'.

This error happens for the following code:

public enum TestVal
{
    First,
    Second,
    Third
}

public class SomeClass<T>
    where T : IComparable<T>
{
    public T Stored
    {
        get
        {
            return storedval;
        }
        set
        {
            storedval = value;
        }
    }
    private T storedval;
}

class Program
{
    static void Main(string[] args)
    {
        //Error is on the next line
        SomeClass<TestVal> t = new SomeClass<TestVal>(); 
    }
}

Since the enum is an int by default and int's implement the IComparable<int> interface it seems like there shouldn't be an error....


Solution

  • Firstly, I'm not sure whether it is sensible to use IComparable<T> with an enum... IEquatable<T>, sure - but comparison?

    As a safer alternative; rather than mandate the IComparable<T> with the generic constraint, perhaps use Comparer<T>.Default inside the class. This has the advantage of supporting IComparable<T> and IComparable - and it means you have less constraints to propagate.

    For example:

    public class SomeClass<T> { // note no constraint
        public int ExampleCompareTo(T other) {
            return Comparer<T>.Default.Compare(Stored, other);
        }
        ... [snip]
    }
    

    This works fine with the enum:

    SomeClass<TestVal> t = new SomeClass<TestVal>();
    t.Stored = TestVal.First;
    int i = t.ExampleCompareTo(TestVal.Second); // -1