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 outmot-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 Addmé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 Barest une sous-classe de Foo, car l' IComparer<in T>interface est contravariante .
Imageest 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 objectgénériques, vous n'avez pas besoin de génériques.
Pour se souvenir facilement de l'utilisation de inet du outmot - 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 Bananaest un type de Fruit,
la fonction qui accepte ISkinned<Fruit>ne pourra accepter ISkinned<Fruit>.
" out T" signifie que ce type Test "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>.
outdemandes de règlement ne Tpeuvent ê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