¿Cuál es la diferencia entre <out T>y <T>? Por ejemplo:
public interface IExample<out T>
{
...
}
vs.
public interface IExample<T>
{
...
}
c#
generics
covariance
Cole Johnson
fuente
fuente

Respuestas:
La
outpalabra clave en genéricos se usa para denotar que el tipo T en la interfaz es covariante. Ver Covarianza y contravarianza para más detalles.El ejemplo clásico es
IEnumerable<out T>. ComoIEnumerable<out T>es covariante, puede hacer lo siguiente:La segunda línea anterior fallaría si esto no fuera covariante, aunque lógicamente debería funcionar, ya que la cadena deriva del objeto. Antes de que se agregaran variaciones en las interfaces genéricas a C # y VB.NET (en .NET 4 con VS 2010), esto fue un error de tiempo de compilación.
Después de .NET 4,
IEnumerable<T>se marcó covariante y se convirtióIEnumerable<out T>. Dado queIEnumerable<out T>solo usa los elementos que contiene y nunca los agrega / cambia, es seguro que trate una colección enumerable de cadenas como una colección enumerable de objetos, lo que significa que es covariante .Esto no funcionaría con un tipo como
IList<T>, ya queIList<T>tiene unAddmétodo. Supongamos que esto se permitiría:Entonces puedes llamar:
Esto, por supuesto, fallaría, por
IList<T>lo que no se puede marcar como covariante.También hay, por cierto, una opción para
in, que es utilizada por cosas como interfaces de comparación.IComparer<in T>, por ejemplo, funciona de manera opuesta. Puede usar un concretoIComparer<Foo>directamente comoIComparer<Bar>siBares una subclase deFoo, porque laIComparer<in T>interfaz es contravariante .fuente
Imagees una clase abstracta;) Puedes hacerlonew List<object>() { Image.FromFile("test.jpg") };sin problemas, o también puedes hacerlonew List<object>() { new Bitmap("test.jpg") };. El problema con el tuyo es quenew Image()no está permitido (tampoco puedes hacerlovar img = new Image();)IList<object>es un ejemplo extraño, si quieresobjectno necesitas genéricos.Para recordar fácilmente el uso de
iny laoutpalabra clave (también covarianza y contravarianza), podemos representar la herencia como envoltura:fuente
considerar,
y las funciones,
La función que acepta
ICovariantSkinned<Fruit>podrá aceptarICovariantSkinned<Fruit>oICovariantSkinned<Bananna>porqueICovariantSkinned<T>es una interfaz covariante yBananaes un tipo deFruit,la función que acepta
ISkinned<Fruit>solo podrá aceptarISkinned<Fruit>.fuente
"
out T" significa que el tipoTes "covariante". Eso limitaTa aparecer solo como un valor devuelto (saliente) en los métodos de la clase genérica, interfaz o método. La implicación es que puede convertir el tipo / interfaz / método a un equivalente con un supertipo deT.Por ejemplo,
ICovariant<out Dog>se puede echar aICovariant<Animal>.fuente
outejecuciones soloTse pueden devolver, hasta que leí esta respuesta. ¡Todo el concepto tiene más sentido ahora!Desde el enlace que publicaste ...
EDITAR : nuevamente, desde el enlace que publicaste
fuente