42 votes

Impossible de convertir à partir de la liste <Bar> lister <Foo>

J'ai une configuration comme celle-ci:

 abstract class Foo {}
class Bar : Foo {}
 

et une méthode ailleurs sous cette forme:

 void AddEntries(List<Foo>) {}
 

J'essaie d'appeler cette méthode en utilisant une liste d'objets de type Bar

 List<Bar> barList = new List<Bar>()
AddEntries(barList);
 

mais cela me donne l'erreur:

ne peut pas convertir de Liste <Bar> en Liste <Foo>

Y at-il de toute façon autour de ce problème? J'ai besoin de conserver la définition de la méthode en utilisant la classe abstraite.

65voto

Mighty Badaboom Points 4981

Vous pouvez rendre votre AddEntries générique et le changer en ceci

 void AddEntries<T>(List<T> test) where T : Foo
{
    //your logic 
}
 

Consultez Contraintes sur les paramètres de type pour plus d'informations.

60voto

Rob Points 24505

Avoir une lecture de la Covariance et la Contravariance dans les Génériques de docs.microsoft.com comme cela, en particulier la section "Interfaces Génériques avec Covariante les Paramètres de Type" va couvrir le scénario que vous travaillez avec.

En bref, si vous (pouvez) modifier la signature de votre AddEntries méthode pour:

static void AddEntries(IEnumerable<Foo> entries)

(Notez l'utilisation de l' IEnumerable<Foo> au lieu de List<Foo>), vous serez en mesure de faire ce que vous voulez.

Le spécifique de la différence ici est que l' IEnumerable<T> et List<T> sont déclarés différemment:

public interface IEnumerable<out T> : IEnumerable
public class List<T> : IList<T>, ... ...

La différence que la matière est l' out dans la déclaration de IEnumerable<T> ce qui indique qu'il est covariant , qui signifie (avec la définition tirée de docs.microsoft.com):

La Covariance: vous Permet d'utiliser un type dérivé que spécifié à l'origine.

43voto

user3185569 Points 22924

Ce n'est pas permis pour une raison simple. Supposons que la compilation ci-dessous:

 AddEntries(new List<Bar>());

void AddEntries(List<Foo> list)
{
   // list is a `List<Bar>` at run-time
   list.Add(new SomethingElseDerivingFromFoo()); // what ?!
}
 

Si votre code compilait, vous avez un ajout dangereux (ce qui rend inutiles toutes les listes génériques) où vous avez ajouté SomethingElseDerivingFromFoo à un List<Bar> (type d'exécution).

Pour résoudre votre problème, vous pouvez utiliser des génériques:

 void AddEntries<T>(List<T> list) where T:Foo
{

}
 

Prograide.com

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.

Powered by:

X