2012-09-18 15 views
22

¿Por qué la propiedad obtiene el error mientras se puede compilar el método?Varianza no válida: el parámetro de tipo 'T' debe ser contravariante en 'UserQuery.IItem <T> .ItemList'. 'T' es covariante

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

error:

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

+0

Posible duplicado de [T debe ser válido de forma contravariable] (https://stackoverflow.com/questions/5041664/t-must-be-contravariantlyvalid) –

Respuesta

27

se obtiene el error del compilador porque tiene una propiedad de captador (get) y un regulador (set). El getter de propiedad tiene el T en su salida para que out funcione, pero el ajustador de propiedad tendrá el T en su entrada por lo que necesitaría el modificador in.

Debido a que tiene out en T tiene que quitar la incubadora y se compilará:

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

Si su T es un in argumento genérico entonces la siguiente funcionaría:

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

Pero no puede tener ambos (out,in) al mismo tiempo, por lo que no puede tener una propiedad co/contravariante con un getter y un setter.

+2

No entiendo esto. Has relacionado, para obtener, establecer. ¿Por qué no puedo utilizar, ya que solo significa "este tipo o cualquier tipo derivado". Si B deriva de A, entonces ¿por qué no puedo pasar B a cualquier propiedad en la interfaz que requiera una salida A, ya que B solo se llamará como si fuera una A de todos modos. ¿Cuál es el problema y qué tiene que ver con esto? en dice "este tipo o cualquier tipo de base". No quiero eso, ya que espero usar al menos el conjunto de comportamientos de A, pasar una "a" no lo cortará. Así que no me gustaría "entrar" ... pero sí quiero ser capaz de establecer B en A. – rism

2

El colocador no está permitido, ya que si se tratara de que sería capaz de hacer esto:

public interface ISubFoo : IFoo { } 

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

que no es de tipo seguro.

Cuestiones relacionadas