Can I specify a "supertype" relationship in general restrictions in C #?

I have a collection class with the Equals method, which I want to pass in the method of checking the correspondence between each element. In addition, I want the delegate type to work on superclasses of T, as well as T itself:

public delegate bool EqualityComparer<T>(T x, T y); public class Collection<T> { //... public bool Equals<U>(Collection<T> other, EqualityComparer<U> eq) where T : U { // code using eq delegate to test equality between // members of this and other collection } } 

Unfortunately, the compiler blocks this ('Collection.Equals ()' does not define a parameter of type 'T'). Is there a way to specify this type of restriction / operation?

+6
generics c # delegates constraints
source share
3 answers

No, I'm afraid you cannot specify such a restriction. (I also wanted this).

You can write a static universal method with two type parameters in a non-universal class:

 public delegate bool EqualityComparer<T>(T x, T y); public class Collection { public static Equals<T, U>(Collection<T> first, Collection<T> second, EqualityComparer<U> comparer) where T : U { } } 

and you can even make this call an instance method in a generic class if you want:

 // Implementing the static method: return first.Equals(second, new EqualityComparer<T>(comparer)); 

where the collection instance method will only be:

 public bool Equals(Collection<T> other, EqualityComparer<T> eq) { // ... } 

This takes advantage of contraception, available for creating delegates from C # 2 onwards.

+4
source share

As John said, you cannot reference T inside a constraint, since it is declared at the class level.

If you can write a method without access to the private state of the collection (or with their internal), you can rewrite it like this:

 public class Collection<T> { ... } public static class CollectionExtentions { public static bool Equals<T,U>( this Collection<T> first, Collection<T> other, EqualityComparer<U> eq) where T : U { ... // legal to use eq here on the T values with collections } } 

By the way, I suggest you use Func<T,T,bool> instead of your named delegate name

+1
source share

If you explicitly want the type parameter to be an inherited class of U, you do not need generics, but rather use U as a formal type of parameters. And there polymorphism breaks in! :)

0
source share

All Articles