2010-05-20 14 views
12

Der folgende Code kann nicht kompiliert werden (mit VS2010) und ich sehe nicht warum. Der Compiler sollte in der Lage sein zu folgern, dass List<TestClass> mit IEnumerable<ITest> "kompatibel" ist (sorry für das Fehlen eines besseren Wortes), aber irgendwie tut es das nicht. Was fehlt mir hier?C# -Compiler erkennt nicht, dass eine Klasse eine Schnittstelle implementiert


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

Der Compiler gibt zwei Fehler:

  1. Die beste überladene Methode Spiel für ‚ConsoleApplication1.Program.Test (System.Collections.Generic.IEnumerable < ConsoleApplication2 .ITest >) 'hat einige ungültige Argumente

  2. Argument: kann nicht von 'System.Collections.Generic.List <ConsoleApplication2.TestClass>' auf 'System.Collections.Generic.IEnumerable <ConsoleApplication2.ITest>'

Antwort

8

Was Sie versuchen, heißt covariance - Konvertieren von einem schmaleren Typ (TestClass) zu einem breiteren Typ (ITest). Es ist etwas, an das Sie die ganze Zeit gewöhnt sein werden, es passiert, wenn Sie zum Beispiel von einem Float zu einem Double konvertieren.

Leider unterstützt .Net 3.5 und niedriger keine Kovarianz in generischen Klassen.

.Net 4.0 unterstützt jetzt Kovarianz (und Kontravarianz) in Generika, sofern diese generischen Klassen mit den Schlüsselwörtern out für kovariante Typen und in für kontravariante Typen kompiliert werden. IEnumerable in .Net 4.0 ist als Kovariante definiert. Wenn Sie direkt am IEnumerable Typ klicken und „goto Definition“ klicken, werden Sie sehen:

public interface IEnumerable<out T> : IEnumerable 

Wenn Sie VS2010 verwenden, müssen Sie Ihr Projekt stellen Sie sicher, .net 4.0 zielt. Dies kann über die Projekteigenschaften geändert werden. Klicken Sie mit der rechten Maustaste auf das Projekt, wählen Sie Eigenschaften, gehen Sie zur Registerkarte "Anwendung" und überprüfen Sie, ob das "Zielframework" für .Net 4 geeignet ist.

MSDN has more information.

2

konvertieren Dies muss mit Varianz umgehen (Kovarianz und Kontravarianz); Überprüfen Sie diese post und die Antwort von Jon Skeet

1

Überprüfen Sie die Zielversion des Frameworks für Ihr Projekt. Dieser Code funktioniert nur in .NET 4.

Verwandte Themen