7

Let's say we have an interface like

public interface IEnumerable<out T>
{ /*...*/ }

that is co-variant in T.

Then we have another interface and a class implementing it:

public interface ISomeInterface {}
public class SomeClass : ISomeInterface
{}

Now the co-variance allows us to do the following

IEnumerable<ISomeInterface> e = Enumerable.Empty<SomeClass>();

So a IEnumerable<SomeClass> is assignable to a variable (or method parameter) of type IEnumerable<ISomeInterface>.

But if we try this in a generic method:

public void GenericMethod<T>(IEnumerable<T> p) where T : ISomeInterface
{
    IEnumerable<ISomeInterface> e = p;
    // or
    TestMethod(p);
}
public void TestMethod(IEnumerable<ISomeInterface> x) {}

we get the compiler error CS0266 telling us that an IEnumerable<T> cannot be converted to an IEnumerable<ISomeInterface>.

The constraint clearly states the T is derived from ISomeInterface, and since IEnumerable<T> is co-variant in T, this assignment should work (as shown above).

Is there any technical reason why this cannot work in a generic method? Or anything I missed that makes it too expensive for the compiler to figure it out?

René Vogt
  • 43,056
  • 14
  • 77
  • 99

1 Answers1

8

Change your GenericMethod and add generic constraint class:

public void GenericMethod<T>(IEnumerable<T> p) where T : class, ISomeInterface
{
    IEnumerable<ISomeInterface> e = p;
    // or
    TestMethod(p);
}

Covariance does not support structs, so we need to tell that we want to use classes only.

Backs
  • 24,430
  • 5
  • 58
  • 85