Hi there,
I've have a class called Edge, with the following signature:
class Edge : IComparable{
...
...
...
}
And another class called CompareEdge, with the following signature:
class CompareEdge<T> : IComparer<T> where T : IComparable<T>
{
...
...
...
}
However, In my test class, the following statement is not compiling:
CompareEdge<Edge> comparer = new CompareEdge<Edge>();
I'm getting the following error:
"The type 'MetroNetwork.Edge' cannot be used as type parameter 'T' in the
generic type or method 'MetroNetwork.CompareEdge<T>'. There is no implicit
reference conversion from 'MetroNetwork.Edge' to
'System.IComparable<MetroNetwork.Edge>'."
Can someone please educate me as to why this is NOT compiling and how to fix
it?
Many thanks,
J
Jon Skeet [C# MVP] - 08 Mar 2008 23:41 GMT
> I've have a class called Edge, with the following signature:
> class Edge : IComparable{
[quoted text clipped - 3 lines]
>
> }
Okay. So there you're implementing the *non-generic* interface.
> And another class called CompareEdge, with the following signature:
> class CompareEdge<T> : IComparer<T> where T : IComparable<T>
And there you're demanding that the type parameter T is only used where
T implements the generic interface IComparable<T>.
> However, In my test class, the following statement is not compiling:
>
[quoted text clipped - 8 lines]
> Can someone please educate me as to why this is NOT compiling and how to fix
> it?
IComparable<T> and IComparable are separate interfaces - they might as
well be IFoo<T> and IBar as far as the compiler is concerned. You need
to change the Edge declaration to:
class Edge : IComparable<Edge>
{
...
}

Signature
Jon Skeet - <skeet@pobox.com>
http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet
World class .NET training in the UK: http://iterativetraining.co.uk
Marc Gravell - 08 Mar 2008 23:42 GMT
Edge must be : IComparable<Edge> in order to meet the contraint in
ComparerEdge<Edge>
Actually, I wonder if you can lose ComparerEdge<T> completely, and
just use the regular Comparer<Edge>.Default?
Marc
James - 09 Mar 2008 00:01 GMT
Jon and Marc, it worked perfectly. Many thanks.
One quick question, before I changed my Edge class declaration to "class
Edge : IComparable<Edge>",
The CompareEdge seemed to compile ok for String, that is:
CompareEdge<String> comparer = new CompareEdge<String>(); worked.
When I check msdn on the String class, it appeared to implement many
interfaces BUT was not generic.
Can someone please educate me why it worked for string?
> Hi there,
>
[quoted text clipped - 30 lines]
> Many thanks,
> J
Peter Duniho - 09 Mar 2008 00:13 GMT
> Jon and Marc, it worked perfectly. Many thanks.
>
[quoted text clipped - 6 lines]
>
> Can someone please educate me why it worked for string?
The constraint you've provided isn't that the T class itself be generic.
It's simply that the T class implements the generic interface
IComparable<T>.
The String class does in fact implement IComparable<String> (well, the
docs say "IComparable<string>" but that's really the same :) ), and so
String is a valid parameter to use for T in creating a concrete instance
of the generic class CompareEdge<T>.
After all, you haven't made your Edge class generic, right? And yet, as
long as it implements IComparable<Edge>, it should work in your
CompareEdge<T> class as well.
All that said, I'm curious as to why you've made CompareEdge<T> a generic
class at all. The name implies to me that you'll only ever use it with
the Edge class. Conversely, it will be confusing to use the class with a
class that's not an edge of some sort. Do you have a variety of classes
that all represent edges in some way? If not, why is CompareEdge<T> a
generic class?
Pete