Alex Marshall
Alex Marshall

Reputation: 10312

c# generics on a method with the constraint that the type must be of "this" type

I have a C# class hierarchy with a common base type and two derived types. I want to declare an abstract method on the base class something like this :

public abstract IEnumerable<T> GetSiblings<T>() where T : MyBaseClass

... and I want this method to be implemented in the derived classes such that T is the type of that derived type, for each of the derived types, ie, in derived class A:

public override IEnumerable<A> GetSiblings<A>() { ... }

... and in derived class B ...

public override IEnumerable<B> GetSiblings<B>() { ... }

Put another way, each derived class must implement the method so that it returns an IEnumerable of items of the same type. Is there any way to implement this in C# ?

Upvotes: 1

Views: 201

Answers (4)

Alex Marshall
Alex Marshall

Reputation: 10312

I found the solution. Apparently in C# 4.0, generic parameter types can be covariant, so what I've posted above will work. C# 3.5 or lower, and it doesn't work. Took a lot of Googling.

Upvotes: 0

Ed Swangren
Ed Swangren

Reputation: 124642

Well, you can hardly call a method generic if it only accepts a parameter of a single type, and your method signatures will have different return types which isn't allowed. Why don't you define an interface for all of these classes and simply return an IEnumerable<IMyClass>?

Upvotes: 2

Anthony Pegram
Anthony Pegram

Reputation: 126834

This is not supported by the type system. It's a common enough problem, represented often as

class Animal<T> where T : Animal<T> { }
class Cat : Animal<Cat> { } // what you desire
class Dog : Animal<Cat> { } // what is possible yet not desired

But not a problem that has as yet been acted upon by the appropriate parties (be it the framework providers or C# team, not sure who).

Until it passes the critical "worth it" test as determined by costs (and opportunity costs) versus benefits, you'll have to work around it.

Upvotes: 0

Stretto
Stretto

Reputation: 486

You can't do this because the return types are different. Simple as that. The reason is if you create an instance of A and stuff it into your base class(cast it) then the return type will be wrong.

You might be able to to use new instead but that might break your hierarchy.

Upvotes: 0

Related Questions