2017-09-25 3 views
-3

Je veux créer une méthode d'extension qui fonctionne sur une liste et d'accepter une autre liste:La méthode d'extension sur ICollection <T> ne change pas la liste d'appels?

public static void Charge<T, S>(this ICollection<T> targetList, ICollection<S> sourceList) where T : class, new() 
     { 
      if (targetList == null || sourceList == null) 
       throw new NullReferenceException(); 
      targetList = new List<T>(); 
      foreach (var item in sourceList) 
      { 
       T t = new T(); 
       //do work on t 
       targetList.Add(t); 
      } 

     } 

mais quand je l'appelle comme ceci:

var targetList = new List<Item>(); 
targetList.Charge(sourceList); 

la targetList ne change pas (articles comptent = 0)

+0

Supprimer 'targetList = new Liste ();' –

+0

Pourquoi faites-vous 'targetList = new Liste ();'? – rbm

+0

Vous ne renvoyez pas la liste cible, vous ne la gérez pas non plus en tant que référence. – Trioj

Répondre

-1

Vous ne pouvez pas affecter une nouvelle instance à targetList si vous transmettez la liste par la valeur. Vous pouvez ajouter, supprimer ou modifier le contenu de la liste existante, mais si vous souhaitez affecter une autre instance, vous devez ajouter le mot clé ref pour autoriser les affectations.

+3

Vous ne pouvez pas marquer 'this' argument de la méthode d'extension avec' ref'. – PetSerAl

+0

Je le sais. Mais puisque les deux sont des collections, vous pouvez échanger des arguments 'public static void Charge (cette ICollection sourceList, réf ICollection targetList)' – Michael

0

La méthode proposée n'a aucun sens pour moi.

Vous souhaitez copier le contenu de la liste source dans la cible, mais vous voulez d'abord remplacer la liste cible pour s'assurer qu'il est vide? Si vous allez de toute façon remplacer la liste des cibles, pourquoi ne pas simplement la remplacer comme ça?

target = source.ToList(); 

Aussi, comment comptez-vous mettre en œuvre le « faire un travail sur t » dans une méthode d'extension générique où l'on ne connaît pas les types de S et T? Pourquoi ne pas faire la chose idiomatiques, .: par exemple

target = source.Select(s => Transform(s)).ToList(); 

Ici, nous supposons Transform est une méthode capable de créer et de remplir un objet cible d'un objet source.

Ou, vous pouvez éviter réaffectant une nouvelle liste en effaçant l'ancien premier:

target.Clear(); 
target.AddRange(source.Select(s => Transform(s))); 

Et si vous vraiment voulez avoir un seul appel, vous pouvez simplement envelopper l'une des solutions ci-dessus, par exemple:

public static List<TTarget> ToList<TSource, TTarget>(
    this IEnumerable<TSource> source, 
    Func<TSource, TTarget> conversion) 
{ 
    if (source == null) 
     throw new ArgumentNullException(nameof(source)); 
    if (conversion == null) 
     throw new ArgumentNullException(nameof(conversion)); 

    return source.Select(conversion).ToList(); 
} 

Utilisation:

target = source.ToList(s => Transform(s)); 
+1

Re: juste en appelant ToList(): Si je comprends bien, le problème est que la source de l'OP La liste est un T différent de la liste cible. Vraiment, OMI, je ne vois pas pourquoi le code entier n'est pas quelque chose comme var newThings = oldThings.Select (chose => ConvertOldThingToNewThing (chose)); – Trioj

+0

Merci, je n'aurais pas compris ce point. –

+0

Pas de soucis. Il m'a fallu honnêtement plus de temps que je l'aurais voulu pour réaliser que c'était juste un appel Select() étrangement conçu avec une transformation. – Trioj