The following code fails to compile (using VS2010) and I don't see why. The compiler should be able to infer that List<TestClass>
is 'compatible' (sorry for lack of a better word) with IEnumerable<ITest>
, but somehow it doesn't. What am I missing here?
interface ITest {
void Test();
}
class TestClass : ITest {
public void Test() {
}
}
class Program {
static void Test(IEnumerable<ITest> tests) {
foreach(var t in tests) {
Console.WriteLine(t);
}
}
static void Main(string[] args) {
var lst = new List<TestClass>();
Test(lst); // fails, why?
Test(lst.Select(t=>t as ITest)); //success
Test(lst.ToArray()); // success
}
}
The compiler gives two errors:
The best overloaded method match for 'ConsoleApplication1.Program.Test(System.Collections.Generic.IEnumerable<ConsoleApplication2.ITest>)' has some invalid arguments
Argument 1: cannot convert from 'System.Collections.Generic.List<ConsoleApplication2.TestClass>' to 'System.Collections.Generic.IEnumerable<ConsoleApplication2.ITest>'
What you are trying to do is called covariance - converting from a narrower type (TestClass) to a wider type (ITest). It's something you'll be used to all the time, it happens when you convert from a float to a double for example.
Unfortunately .Net 3.5 and lower does not support covariance in generic classes.
.Net 4.0 now does support covariance (and contravariance) in generics, provided those generic classes are compiled with the keywords out
for covariant types and in
for contravarient types. IEnumerable
in .Net 4.0 is defined as covariant. If you right click on the IEnumerable
type and click "goto definition", you'll see this:
public interface IEnumerable<out T> : IEnumerable
If you are using VS2010, you will need to make sure your project is targeting .net 4.0. This can be changed from the project properties. Right click on the project, select properties, goto the "Application" tab and check that the "Target framework" is to to .Net 4.
MSDN has more information.
This has to do with variance (covariance and contravariance); check out this post and the answer by Jon Skeet
Check the Target Version of the framework for your project. This code will only work in .NET 4 .
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With