Quelle est la différence entre <out T>
y <T>
? Par exemple :
public interface IExample<out T>
{
...
}
vs.
public interface IExample<T>
{
...
}
Quelle est la différence entre <out T>
y <T>
? Par exemple :
public interface IExample<out T>
{
...
}
vs.
public interface IExample<T>
{
...
}
En out
Le mot clé dans les génériques est utilisé pour indiquer que le type T dans l'interface est covariant. Voir Covariance et contravariance pour les détails.
L'exemple classique est IEnumerable<out T>
. Puisque IEnumerable<out T>
est covariant, vous êtes autorisé à faire ce qui suit :
IEnumerable<string> strings = new List<string>();
IEnumerable<object> objects = strings;
La deuxième ligne ci-dessus échouerait si elle n'était pas covariante, même si logiquement elle devrait fonctionner, puisque string dérive de object. Avant la variance des interfaces génériques a été ajouté à C# et VB.NET (dans .NET 4 avec VS 2010), il s'agissait d'une erreur de compilation.
Après .NET 4, IEnumerable<T>
a été marqué covariant, et est devenu IEnumerable<out T>
. Puisque IEnumerable<out T>
n'utilise que les éléments qu'il contient et ne les ajoute ni ne les modifie jamais. Il peut donc traiter une collection énumérable de chaînes de caractères comme une collection énumérable d'objets. covariant .
Cela ne fonctionnerait pas avec un type comme IList<T>
puisque IList<T>
a un 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
Ce serait, bien sûr, un échec - donc IList<T>
ne peut pas être marqué covariant.
Il y a aussi, entre-temps, une option de in
- qui est utilisé par des choses comme les interfaces de comparaison. IComparer<in T>
par exemple, fonctionne de manière inverse. Vous pouvez utiliser un IComparer<Foo>
directement en tant que IComparer<Bar>
si Bar
est une sous-classe de Foo
parce que le IComparer<in T>
L'interface est contravariant .
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>
sera en mesure d'accepter ICovariantSkinned<Fruit>
ou ICovariantSkinned<Banana>
parce que ICovariantSkinned<T>
est une interface covariante et Banana
est un type de Fruit
,
la fonction qui accepte ISkinned<Fruit>
ne pourra accepter que ISkinned<Fruit>
.
" out T
"signifie que le type T
est "covariant". Cela restreint T
pour n'apparaître que comme 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 couler le type/interface/méthode vers un équivalent avec un super-type de T
.
Par exemple ICovariant<out Dog>
peut être transformé en ICovariant<Animal>
.
Du lien que vous avez posté....
Pour les paramètres de type générique, t est covariant .
EDIT : Encore une fois, d'après le lien que vous avez posté
Pour plus d'informations, voir Covariance et Contravariance (C# et Visual Basic). http://msdn.microsoft.com/en-us/library/ee207183.aspx
Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.