C# compiler fails to recognize a class is implementing an interface

.net, .net-4.0, c#, covariance, generics

Solution

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.

Problem

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>'

Original source

Related problems