C# boxing enum error with generics
Asked Answered
C

4

6

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

Cwmbran answered 23/6, 2009 at 7:25 Comment(1)
int's implement IComparable<int> but that doesn't mean RandomEnumType implements IComparable<RandomEnumType>.Strachan
L
9

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
Lansquenet answered 23/6, 2009 at 7:38 Comment(1)
Thanks for the possible alternate solution to my problem. The actual code is very deep in a test framework that needs to handle just about any type of test data. I'll have to do some more investigation but it seems like your code might be a better way to deal with the compare in my generic objects....Cwmbran
R
5

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.

Rabbet answered 23/6, 2009 at 7:36 Comment(2)
(I fixed the markdown - and then went crazy and edited your answer instead of my own! Fixed now; sorry about that...)Lansquenet
Thanks for the explanation. That helps. It also makes me wonder if I will have the same kind of problem with structs....Cwmbran
Z
1

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);
    }
}
Zenobiazeolite answered 23/6, 2009 at 8:45 Comment(0)
T
0

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.

Thymelaeaceous answered 23/6, 2009 at 7:32 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.