Marc et CodeInChaos réponses sont assez bon, mais juste pour ajouter un peu plus de détails:
Tout d'abord, il semble que vous êtes intéressé à en apprendre sur le processus de conception, nous sommes allés à travers pour rendre cette fonctionnalité. Si oui, alors je vous invite à lire ma longue série d'articles que j'ai écrit lors de la conception et de la mise en œuvre de la fonctionnalité. Commencer par le bas:
http://blogs.msdn.com/b/ericlippert/archive/tags/covariance+et+la contravariance/par défaut.aspx
Est-il juste pour faire de l'ennuyeux jette dans les expressions LINQ s'en aller?
Non, il n'est pas juste pour éviter Cast<T>
expressions, mais cela a été l'un des facteurs de motivation qui nous a encouragés à faire de cette fonctionnalité. Nous avons réalisé qu'il y aurait une légère hausse dans le nombre de "pourquoi ne puis-je pas utiliser une séquence de Girafes dans cette méthode qui prend une séquence d'Animaux?", questions, parce que LINQ encourage l'utilisation des types de séquence. Nous savions que nous voulions ajouter la covariance pour IEnumerable<T>
première.
Nous avons effectivement envisagé IEnumerable<T>
covariante même en C# 3, mais a décidé qu'il serait étrange de le faire sans l'introduction de la fonction entière pour quiconque de l'utiliser.
Ne pas ce présenter les mêmes problèmes comme avec string[] <: object[]
(cassé la matrice de variance) en C#?
Il n'est pas directement introduire ce problème parce que le compilateur ne permet à l'écart quand il est connu pour être typesafe. Cependant, il n' préserver le cassé de la matrice de variance problème. Avec la covariance, IEnumerable<string[]>
est implicitement convertible IEnumerable<object[]>
, donc si vous avez une séquence de tableaux de chaîne, vous pouvez traiter que comme une suite de tableaux d'objets, et puis vous avez le même problème qu'avant: vous pouvez essayer de mettre une Girafe dans le tableau de chaîne et obtenir une exception à l'exécution.
Comment a été l'ajout de la covariance fait à partir d'une compatibilité point de vue?
Soigneusement.
Sera plus tôt code de toujours travailler sur les dernières versions de .NET ou est-recompilation nécessaire ici?
Une seule façon de le savoir. Essayez et voyez ce ne!
C'est souvent une mauvaise idée d'essayer de forcer le code compilé contre .NET X pour exécuter sur .NET Y si X != Y, quelle que soit le type de système.
Ce sujet dans l'autre sens?
Même réponse.
Est-il possible que dans certains cas va se comporter de manière différente aujourd'hui?
Absolument. Faire une interface covariante où il était invariant avant est techniquement une "modification importante", car il peut causer code de travail à la pause. Par exemple:
if (x is IEnumerable<Animal>)
ABC();
else if (x is IEnumerable<Turtle>)
DEF();
Lors de l' IE<T>
n'est pas covariante, ce code choisit soit ABC ou DEF ou aucun des deux. Quand il est covariant, il n'a jamais choisit DEF plus.
Ou:
class B { public void M(IEnumerable<Turtle> turtles){} }
class D : B { public void M(IEnumerable<Animal> animals){} }
Avant, si vous l'avez appelé M sur une instance de D avec une séquence de tortues marines, le raisonnement, la résolution de surcharge choisit B. M parce que c'est la seule méthode applicable. Si IE est covariant, puis la résolution de surcharge choisit D. M parce que les deux méthodes sont applicables, et une méthode applicable sur une classe dérivée de bat toujours une méthode applicable sur une classe dérivée, indépendamment du fait que l'argument de type match-ci, est exact ou pas.
Ou:
class Weird : IEnumerable<Turtle>, IEnumerable<Banana> { ... }
class B
{
public void M(IEnumerable<Banana> bananas) {}
}
class D : B
{
public void M(IEnumerable<Animal> animals) {}
public void M(IEnumerable<Fruit> fruits) {}
}
Si IE est invariante alors un appel à l' d.M(weird)
décide de B. M. Si IE devient tout à coup covariante puis les deux méthodes D. M sont applicables, les deux sont meilleurs que la méthode de la classe de base, et aucune n'est meilleure que l'autre, donc, de résolution de surcharge devient ambigu et nous signaler une erreur.
Lorsque nous avons décidé de faire ces modifications importantes, nous espérions que (1) les situations sont rares, et (2) lorsque de telles situations surviennent, presque toujours, c'est parce que l'auteur de la classe est de tenter de simuler la covariance dans une langue qui ne l'a pas. Par l'ajout de covariance directement, j'espère quand le code "casse" sur la recompilation, l'auteur peut tout simplement supprimer la folle engins en essayant de simuler une fonctionnalité qui existe maintenant.