Comment puis-je écrire une méthode d'extension générique pour convertir une liste à un HashSet en utilisant HashSet.AddRange ()?
-
22-09-2019 - |
Question
HashSet n'a pas une méthode AddRange, donc je veux écrire une méthode d'extension pour elle. Voilà ce que j'ai:
public static void AddRange<T>(this ICollection<T> collection, IEnumerable<T> list)
{
foreach (var item in list)
{
collection.Add(item);
}
}
J'ai une classe de base, les médias, et une classe dérivée, Photo. Voici le code que je veux travailler:
var photos = new List<Photo>();
var media = new HashSet<Media>();
media.AddRange(photos);
Cependant, le compilateur me dit qu'il ne peut pas convertir le List<Photo>
à IEnumerable<Media>
lorsque je tente d'utiliser AddRange()
. Je suis sûr que ce soit parce que je IEnumerable<T>
dans la méthode d'extension, mais comment puis-je l'écrire afin que le type est différent de celui du type à AddRange<T>
?
La solution
Une autre question-variance générique. Vous devez appeler la méthode d'extension Cast<Media>
pour convertir le IEnumerable<Photo>
à IEnumerable<Media>
avant qu'il ne soit acceptable pour la signature de votre mise en œuvre de AddRange
.
Vous pouvez déclarer
AddRange<T, U>(ICollection<T>, IEnumerable<U>) where U : T
en tant que solution pour produire la variance correcte dans la signature.
Autres conseils
En fait, HashSet<T>
peut ne pas avoir une méthode de AddRange
, mais il a une méthode UnionWith
, qui est sémantiquement ce que vous recherchez. La différence de nom reflète le fait qu'il filtre les doublons. Il dispose également d'un constructeur qui prend un IEnumerable<T>
comme paramètre, si vous voulez juste copier une collection dans un HashSet
.
Dans le cas général, la réponse ci-dessus recommandant d'utiliser une contrainte générique (le « where T : U
») est correct.