Qual é a diferença entre <out T>
e <T>
? Por exemplo:
public interface IExample<out T>
{
...
}
vs.
public interface IExample<T>
{
...
}
c#
generics
covariance
Cole Johnson
fonte
fonte
Respostas:
A
out
palavra-chave em genéricos é usada para indicar que o tipo T na interface é covariante. Consulte Covariância e contravariância para obter detalhes.O exemplo clássico é
IEnumerable<out T>
. ComoIEnumerable<out T>
é covariante, você pode fazer o seguinte:A segunda linha acima falharia se isso não fosse covariante, mesmo que logicamente funcione, pois a string deriva do objeto. Antes de a variação nas interfaces genéricas ser adicionada ao C # e ao VB.NET (no .NET 4 com VS 2010), era um erro de tempo de compilação.
Após o .NET 4,
IEnumerable<T>
foi marcado covariante e tornou-seIEnumerable<out T>
. ComoIEnumerable<out T>
apenas usa os elementos contidos nele e nunca os adiciona / altera, é seguro tratar uma coleção enumerável de strings como uma coleção enumerável de objetos, o que significa que é covariante .Isso não funcionaria com um tipo como
IList<T>
, poisIList<T>
possui umAdd
método Suponha que isso seja permitido:Você pode ligar para:
Obviamente, isso falharia - portanto,
IList<T>
não pode ser marcado como covariante.Também existe uma opção para
in
- que é usada por coisas como interfaces de comparação.IComparer<in T>
, por exemplo, funciona da maneira oposta. Você pode usar um concretoIComparer<Foo>
diretamente como umIComparer<Bar>
ifBar
é uma subclasse deFoo
, porque aIComparer<in T>
interface é contravariante .fonte
Image
é uma classe abstrata;) Você pode fazernew List<object>() { Image.FromFile("test.jpg") };
sem problemas ounew List<object>() { new Bitmap("test.jpg") };
também. O problema com o seu é quenew Image()
não é permitido (você não pode fazervar img = new Image();
qualquer um)IList<object>
é um exemplo bizarro, se você desejaobject
s, não precisa de genéricos.Para lembrar facilmente o uso
in
e aout
palavra - chave (também covariância e contravariância), podemos imaginar a herança como quebra automática:fonte
considerar,
e as funções,
A função que aceita
ICovariantSkinned<Fruit>
poderá aceitarICovariantSkinned<Fruit>
ouICovariantSkinned<Bananna>
porqueICovariantSkinned<T>
é uma interface covariante eBanana
é um tipo deFruit
,a função que aceita
ISkinned<Fruit>
somente poderá aceitarISkinned<Fruit>
.fonte
"
out T
" significa que o tipoT
é "covariante". Isso restringeT
a aparecer apenas como um valor retornado (de saída) nos métodos da classe, interface ou método genérico. A implicação é que você pode converter o tipo / interface / método em um equivalente com um supertipo deT
.Por exemplo,
ICovariant<out Dog>
pode ser lançado paraICovariant<Animal>
.fonte
out
reforças queT
podem ser retornadas apenas, até que eu li esta resposta. Todo o conceito faz mais sentido agora!No link que você postou ....
EDIT : novamente, a partir do link que você postou
fonte