Quelle est la différence entre <out T>
et <T>
? Par exemple:
public interface IExample<out T>
{
...
}
contre.
public interface IExample<T>
{
...
}
Quelle est la différence entre <out T>
et <T>
? Par exemple:
public interface IExample<out T>
{
...
}
contre.
public interface IExample<T>
{
...
}
Réponses:
Le out
mot-clé en générique est utilisé pour indiquer que le type T dans l'interface est covariant. Voir Covariance et contravariance pour plus de détails.
L'exemple classique est IEnumerable<out T>
. Puisque IEnumerable<out T>
est covariant, vous êtes autorisé à effectuer les opérations suivantes:
IEnumerable<string> strings = new List<string>();
IEnumerable<object> objects = strings;
La deuxième ligne ci-dessus échouerait si ce n'était pas covariant, même si logiquement cela devrait fonctionner, puisque string dérive de object. Avant l' ajout de la variance dans les interfaces génériques à C # et VB.NET (dans .NET 4 avec VS 2010), il s'agissait d'une erreur de compilation.
Après .NET 4, a IEnumerable<T>
été marqué comme covariant et est devenu IEnumerable<out T>
. Comme IEnumerable<out T>
il n'utilise que les éléments qu'il contient, et ne les ajoute / ne change jamais, il est prudent de traiter une collection énumérable de chaînes comme une collection énumérable d'objets, ce qui signifie qu'elle est covariante .
Cela ne fonctionnerait pas avec un type comme IList<T>
, car IList<T>
a une Add
méthode. Supposons que cela soit autorisé:
IList<string> strings = new List<string>();
IList<object> objects = strings; // NOTE: Fails at compile time
Vous pourriez alors appeler:
objects.Add(new Image()); // This should work, since IList<object> should let us add **any** object
Cela échouerait, bien sûr, et ne IList<T>
peut donc pas être marqué comme covariant.
Il y a aussi, btw, une option pour in
- qui est utilisée par des choses comme les interfaces de comparaison. IComparer<in T>
, par exemple, fonctionne dans le sens inverse. Vous pouvez utiliser un béton IComparer<Foo>
directement comme IComparer<Bar>
si Bar
est une sous-classe de Foo
, car l' IComparer<in T>
interface est contravariante .
Image
est une classe abstraite;) Vous pouvez le faire new List<object>() { Image.FromFile("test.jpg") };
sans problème, ou vous pouvez le faire new List<object>() { new Bitmap("test.jpg") };
aussi. Le problème avec le vôtre est que ce new Image()
n'est pas autorisé (vous ne pouvez pas le faire non var img = new Image();
plus)
IList<object>
est un exemple bizarre, si vous voulez des object
génériques, vous n'avez pas besoin de génériques.
Pour se souvenir facilement de l'utilisation de in
et du out
mot - clé (également covariance et contravariance), nous pouvons représenter l'héritage comme un wrapping:
String : Object
Bar : Foo
considérer,
class Fruit {}
class Banana : Fruit {}
interface ICovariantSkinned<out T> {}
interface ISkinned<T> {}
et les fonctions,
void Peel(ISkinned<Fruit> skinned) { }
void Peel(ICovariantSkinned<Fruit> skinned) { }
La fonction qui accepte ICovariantSkinned<Fruit>
pourra accepter ICovariantSkinned<Fruit>
ou ICovariantSkinned<Bananna>
car ICovariantSkinned<T>
est une interface covariante et Banana
est un type de Fruit
,
la fonction qui accepte ISkinned<Fruit>
ne pourra accepter ISkinned<Fruit>
.
" out T
" signifie que ce type T
est "covariant". Cela limite T
à apparaître uniquement comme une valeur retournée (sortante) dans les méthodes de la classe, de l'interface ou de la méthode générique. L'implication est que vous pouvez convertir le type / interface / méthode en un équivalent avec un super-type de T
.
Par exemple, ICovariant<out Dog>
peut être jeté vers ICovariant<Animal>
.
out
demandes de règlement ne T
peuvent être retournées que lorsque j'ai lu cette réponse. L'ensemble du concept a plus de sens maintenant!
À partir du lien que vous avez publié ...
Pour les paramètres de type générique, le mot clé out spécifie que le paramètre de type est covariant .
EDIT : Encore une fois, à partir du lien que vous avez publié
Pour plus d'informations, consultez Covariance et Contravariance (C # et Visual Basic). http://msdn.microsoft.com/en-us/library/ee207183.aspx