web-dev-qa-db-fra.com

Impossible de convertir de la liste <Bar> en liste <Foo>

J'ai une configuration comme celle-ci:

abstract class Foo {}
class Bar : Foo {}

et une méthode ailleurs de 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:

impossible de convertir de la liste <Bar> en liste <Foo>

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

42
user3041702

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

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

Jetez un œil à Contraintes sur les paramètres de type pour plus d'informations.

65
Mighty Badaboom

Lisez Covariance et Contravariance dans les génériques de docs.Microsoft.com comme ceci, en particulier la section "Interfaces génériques avec des paramètres de type covariant" couvrira hors du scénario avec lequel vous travaillez.

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

static void AddEntries(IEnumerable<Foo> entries)

(Notez l'utilisation de IEnumerable<Foo> au lieu de List<Foo>) vous pourrez faire ce que vous cherchez à faire.

La différence spécifique ici est que le 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 qui importe est le out dans la déclaration de IEnumerable<T> qui indique que c'est covariant ce qui signifie (avec la définition tirée de docs.Microsoft.com):

Covariance : vous permet d'utiliser un type plus dérivé que celui spécifié à l'origine.

60
Rob

Ceci n'est pas autorisé pour une simple raison. Supposons que les compilations 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
{

}
43
Zein Makki