2010-05-20 8 views
12

Il seguente codice non riesce a compilare (utilizzando VS2010) e non vedo perché. Il compilatore dovrebbe essere in grado di dedurre che List<TestClass> è "compatibile" (mi dispiace per mancanza di una parola migliore) con IEnumerable<ITest>, ma in qualche modo non è così. Cosa mi manca qui?Il compilatore C# non riconosce che una classe sta implementando un'interfaccia


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

Il compilatore dà due errori:

  1. La partita metodo migliore overload per 'ConsoleApplication1.Program.Test (System.Collections.Generic.IEnumerable < ConsoleApplication2 .ITest >) "ha alcuni argomenti non validi

  2. Argomento 1: non può convertire da 'System.Collections.Generic.List <ConsoleApplication2.TestClass>' a 'System.Collections.Generic.IEnumerable <ConsoleApplication2.ITest>'

risposta

8

Quello che si sta tentando di fare si chiama covariance - la conversione da un tipo più ristretto (TestClass) a un tipo più ampio (ITest). È qualcosa che sarai sempre abituato, succede quando converti da un float in un double, ad esempio.

Sfortunatamente .Net 3.5 e versioni precedenti non supporta la covarianza nelle classi generiche.

.Net 4.0 ora supporta la covarianza (e la contravarianza) in generici, a condizione che tali classi generiche siano compilate con le parole chiave out per i tipi covarianti e in per i tipi controversi. IEnumerable in .Net 4.0 è definito come covariante. Se si fa clic destro sul tipo IEnumerable e fare clic su "Definizione goto", vedrete questo:

public interface IEnumerable<out T> : IEnumerable 

Se si sta utilizzando VS2010, avrete bisogno per assicurarsi che il progetto si rivolge .net 4.0. Questo può essere modificato dalle proprietà del progetto. Fare clic con il tasto destro del mouse sul progetto, selezionare Proprietà, accedere alla scheda "Applicazione" e verificare che "Target framework" sia quello di .Net 4.

MSDN has more information.

2

Questo deve fare con varianza (covarianza e controvarianza); controlla questo post e la risposta di Jon Skeet

1

Controlla la versione di destinazione del framework per il tuo progetto. Questo codice funzionerà solo in .NET 4.

Problemi correlati