web-dev-qa-db-fra.com

Impossible de convertir implicitement la liste <T> en collection <T>

Ceci est une erreur du compilateur (légèrement modifiée pour la lisibilité).

Celui-ci m'a toujours intrigué. FxCop indique qu'il est mauvais de renvoyer une liste et que les classes\dérivées de Collection<T> devraient être préférables en tant que types de retour.

En outre, FxCop indique qu'il est correct d'utiliser List<T> pour le stockage de données interne\manipulation ..__ OK, je comprends, mais ce que je ne comprends pas, c'est que le compilateur se plaint d'avoir tenté de convertir implicitement List<T> en Collection<T>. List<T> n'est-il pas plus chargé d'interface et fonctionnel? Pourquoi interdire la conversion implicite?

Et une autre question qui vient d’en haut: le constructeur new List<int>(some collection<int>) est-il cher?

Je vous remercie,

Valentin Vasiliev 

40
Valentin

List<T> ne dérive pas de Collection<T> - il implémente toutefois ICollection<T>. Ce serait un meilleur choix de type de retour.

Quant à la question new List<int>(some collection<int>) - cela dépend en partie de ce que la collection est. S'il implémente ICollection<T> (au moment de l'exécution), le constructeur peut utiliser sa propriété Count pour créer la liste avec la bonne capacité initiale avant de l'itérer et d'ajouter chaque élément. S'il n'implémente pas ICollection<T>, c'est simplement équivalent à:

List<int> list = new List<int>();
foreach (int x in otherCollection)
{
    list.Add(x);
}

Toujours agréable d'avoir un constructeur pratique, mais pas extrêmement efficace - ça ne peut pas être, vraiment.

Je ne crois pas que le constructeur fasse quelque chose de rusé pour les tableaux, ce qu'il pourrait potentiellement - en utilisant Array.Copy ou autre pour copier simplement le lot en une seule fois plutôt que d'itérer. (De même, s'il s'agissait d'un autre List<T>, il pourrait accéder directement au tableau de sauvegarde et le copier.)

35
Jon Skeet

Pourquoi ne pas simplement faire ce qui suit:

Collection<string> collection = new Collection<string>(theList);

as Collection (entrée IList) prend une liste dans le cadre de la construction.

89
Matthew M.

List<T> n'hérite pas de Collection<T>. Clair et simple. À moins que List<T> ne fournisse un opérateur pour convertir implicitement vers/depuis Collection<T>, vous ne pouvez pas le faire. En fait, je suggèrerais de renvoyer List<T> si vous le pouvez, car je crois que les règles vont comme ceci:

Accepter comme paramètre l'interface la moins contraignante possible. Retourne comme paramètre de retour le type le plus contraignant possible. 

6
David Morton

Voici une méthode d'extension générique écrite en C # 3.0 utilisée pour convertir List<T> en Collection<T>

using System.Collections.Generic;
using System.Collections.ObjectModel;

public static class ExtensionMethods
{
    public static Collection<T> ToCollection<T>(this List<T> items)
    {
        Collection<T> collection = new Collection<T>();

        for (int i = 0; i < items.Count; i++)
        {
            collection.Add(items[i]);
        }

        return collection;
    }
}

et c'est utilisé comme ça…

List<string> entities = new List<string>();
entities.Add("Value 1");
entities.Add("Value 2");
entities.Add("Value 3");
entities.Add("Value 4");

Collection<string> convertedEntities = entities.ToCollection<string>();
4
Keith Beller

Vous pouvez utiliser le la ci-dessous 

public class EmployeeCollection : Collection<Employee>
{
      public EmployeeCollection(IList<Employee> list) : base(list)
      {}

      public EmployeeCollection() : base()
      {}

}

Utilisez la classe comme ça

EmployeeCollection  employeeCollection = new EmployeeCollection(list)
0
Bala Subramaniam

Voici comment vous convertissez de List<T> à Collection<T> (avec LINQ):

L'ancienne fonction:

public List<Employee> GetEmployee(int id)
{
     return ( from e in MyDataContext.Employees
                   select new Employee()
                   {
                     e.empId = id
                   }
             ).ToList();
}

Après conversion:

using System.Collection.ObjectModel;

public Collection<Employee> GetEmployee(int id)
{
           return new Collection<Employee>( 
               (from e in MyDataContext.Employees
                     select new Employee()
                     {
                       e.empId = id
                     }
                ).ToList() as IList<Employee>
           );
}
0
Shadi Namrouti