remarks example cref c# .net generics covariance contravariance

example - remarks c#



T debe ser contravariante vĂ¡lido (3)

Considere lo que sucedería si el compilador lo permitiera:

interface IR<out T> { void D(T t); } class C : IR<Mammal> { public void D(Mammal m) { m.GrowHair(); } } ... IR<Animal> x = new C(); // legal because T is covariant and Mammal is convertible to Animal x.D(new Fish()); // legal because IR<Animal>.D takes an Animal

Y tú solo intentaste cultivar pelo en un pez.

La "salida" significa "T solo se usa en posiciones de salida". Lo estás usando en una posición de entrada.

¿Qué está mal con esto?

interface IRepository<out T> where T : IBusinessEntity { IQueryable<T> GetAll(); void Save(T t); void Delete(T t); }

Dice:

Varianza no válida: el parámetro de tipo ''T'' debe ser contravariante en ''MyNamespace.IRepository.Delete (T)''. ''T'' es covariante.


Los siguientes dos métodos son incorrectos:

void Save(T t); void Delete(T t);

No puede tener T como argumento de método. Solo como tipo de devolución si desea que sea covariante ( out T ) en su definición genérica.

O si quiere contravarianza, puede usar el parámetro genérico solo como argumento de método y no como tipo de retorno:

interface IRepository<in T> where T : IBusinessEntity { void Save(T t); void Delete(T t); }


Puede utilizar un parámetro de tipo de out solo de forma coherente, es decir, en el tipo de devolución. Por lo tanto, IQueryable<T> GetAll() es correcto, pero void Delete(T t) no lo es.

Como T se usa de forma co y contravariante en su clase, no puede usar aquí (ni in ).

Si quieres saber más sobre los antecedentes teóricos detrás de esto, toma un descanso rápido y lee el artículo de Wikipedia "Covarianza y Contravarianza" .

Dar una buena acogida. Entonces, ¿qué haces si necesitas todos esos métodos en tu repositorio pero aún necesitas una interfaz covariante? Puede extraer la parte covariante en su propia interfaz:

interface IDataSource<out T> where T : IBusinessEntity { IQueryable<T> GetAll(); } interface IRepository<T> : IDataSource<T> where T : IBusinessEntity { void Save(T t); void Delete(T t); }

Así es como el .NET BCL resuelve este problema: IEnumerable<out T> es covariante, pero solo admite "operaciones de lectura". ICollection<T> es un subtipo de IEnumerable<out T> , permite operaciones de lectura y escritura, y, por lo tanto, no puede ser covariante.