2012-10-05 22 views
19

Przyjmijmy, mam interfejs i klasa:Dlaczego kowariancji nie działa metoda rodzajowa

public interface ITree {} 
public class Tree : ITree {} 

Jak IEnumerable<T> jest kowariantna linia kodu poniżej jest skompilowany z powodzeniem:

IEnumerable<ITree> trees = new List<Tree>(); 

ale kiedy umieść go w ogólnej metodzie:

public void Do<T>() where T : ITree 
{ 
    IEnumerable<ITree> trees = new List<T>(); 
} 

I skompilowany błąd z kompilatora:

Błąd 1 Nie można niejawnie przekonwertować typu "System.Collections.Generic.List" na "System.Collections.Generic.IEnumerable". Wyraźne konwersji istnieje (czy brakuje obsady?) D: \ lab \ Lab.General \ Lab.General \ Program.cs 83 40 Lab.General

Dlaczego kowariancji nie działa w tym przypadku?

+0

możliwe duplikat [? Czy to jest bug kowariancji w C# 4] (http://stackoverflow.com/questions/2783233/is-this-a-covariance -bug-in-c-sharp-4) – nawfal

Odpowiedz

22

Dzieje się tak, ponieważ wariancja działa tylko z typami odniesienia (klasy, interfejsy & delegatów). Dodaj ograniczenie klasy i kompiluje dobrze:

public static void Do<T>() where T : class, ITree 
+1

Dziękuję, wprowadzam w błąd, że przy ograniczeniu 'T: ITree' jest niejawne, że T jest typem odniesienia, ale tak naprawdę nie jest –

+0

Jeśli' ITree' jest typem interfejsu, to lokalizacja przechowywania typu 'ITree' zawsze będzie zawierała' null' lub odniesienie do obiektu stosu, który implementuje 'ITree', ale miejsce przechowywania typu ogólnego ograniczonego do' ITree' może przechowywać referencję lub może zawierać rzeczywistą instancja typu wartości, która implementuje 'ITree'. Osobiście nie podoba mi się sposób, w jaki konstruktory implementujące interfejsy są niejawnie konwertowane na odwołania do sterty, które implementują te interfejsy, bez konieczności odwoływania się do struktur. Semantyka typu wartości różni się od semantyki reedycji w PRZYDATNE sposoby, ale ... – supercat

+0

... model "systemu jednolitego typu" zakłada (niesłusznie), że będą zachowywać się identycznie. Zmienna typu 'List .Enumerator' implementuje' IEnumerable ', ale zawiera coś, czego zachowanie różni się znacznie od zmiennej typu' IEnumerable ', która zawiera odniesienie do' List .Enumerator'. – supercat

Powiązane problemy