Question

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....

Was it helpful?

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

OTHER TIPS

Enums do not derive from System.Int32s - they derive from System.Enum, which doesn't implement IComparable<int> (it does implement IComparable, though).

Although an enum's underlying value is an int by default, the enum itself isn't. Thus, there is no conversion between the two.

Enum doesn't implement IComparable<T>, but it does implement IComparable. So an enum can be the T in a where clause like:

    where T : IComparable

but this gives an error:

    where T : IComparable<T>

And then I suppose you'd like SomeClass to be comparable. To do that, it would have to implement IComparable itself.

Here's an example of both (using a public member to keep the code simple):

public class SomeClass<T>
    : IComparable<SomeClass<T>>
    where T : IComparable
{
    public T storedval;

    public int CompareTo(SomeClass<T> other)
    {
        return storedval.CompareTo(other.storedval);
    }
}

In C# enums implement IComparable, but not the generic IComparable<T>. I'm not sure why this is, but maybe you could switch to the non-generic IComparable in your where clause.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top