2012-09-18 9 views
22

Dlaczego właściwość otrzymuje błąd podczas kompilacji metody?Nieprawidłowa wariancja: parametr typu "T" musi być niepoprawnie poprawny w "UserQuery.IItem <T> .ItemList". "T" jest kowariantem

public interface IFoo {} 
public interface IBar<out T> where T : IFoo {} 

public interface IItem<out T> where T: IFoo 
{ 
    // IEnumerable<IBar<T>> GetList(); // works 
    IEnumerable<IBar<T>> ItemList { get; set; } // Error! 
} 

Błąd:

Invalid variance: The type parameter 'T' must be contravariantly valid on 'UserQuery.IItem<T>.ItemList'. 'T' is covariant.

+0

Prawdopodobny duplikat [T musi być sprzeczny z prawdą] (https://stackoverflow.com/questions/5041664/t-must-be-contravariantly-valid) –

Odpowiedz

27

Otrzymasz błąd kompilatora, ponieważ masz getter posesji (get) i setter (set). Właściwość getter ma numer T na wyjściu, więc out działa, ale narzędzie ustawiające właściwości będzie miało wejście T, więc będzie potrzebować modyfikatora in.

Ponieważ masz out na T trzeba usunąć setter i będzie skompilować:

public interface IItem<out T> where T : IFoo 
{ 
    // IEnumerable<IBar<T>> GetList(); // works 
    IEnumerable<IBar<T>> ItemList { get; } // also works 
} 

Jeśli Twój T jest in generic argumentem wtedy następujące będzie działać:

public interface IItem<in T> where T : IFoo 
{ 
    IEnumerable<IBar<T>> ItemList { set; } 
} 

Ale nie możesz mieć jednocześnie obu (out,in), więc nie możesz mieć własności współkonwersyjnej z programem pobierającym i seterem.

+2

Nie rozumiem tego. Jesteś spokrewniony, aby zdobyć, ustawić. Dlaczego nie mogę użyć, ponieważ out oznacza po prostu "ten typ lub jakikolwiek rodzaj pochodny.". Jeśli B pochodzi od A, to dlaczego nie mogę przekazać B do żadnej właściwości interfejsu, która wymaga wyjścia A, ponieważ B będzie wywołane tylko tak, jakby to było A. Na czym polega problem i co to ma wspólnego? w polu "ten typ lub dowolny typ bazowy". Nie chcę tego, ponieważ spodziewam się użyć przynajmniej zestawu zachowań A, przejście przez "a" go nie przerwie. Więc nie chciałbym "w" ... ale chcę móc ustawić B na out A. – rism

2

Setter nie jest dozwolone, ponieważ gdyby było byłbyś w stanie to zrobić:

public interface ISubFoo : IFoo { } 

IItem<ISubFoo> item = //whatever 
item.ItemList = new List<IBar<IFoo>>>(); 

który nie jest typu bezpieczne.

Powiązane problemy