45 votes

Impossible de convertir implicitement List<T> en Collection<T>

Il s'agit d'une erreur de compilation (légèrement modifiée pour des raisons de lisibilité).

Celle-ci m'a toujours laissé perplexe. FxCop indique que c'est une mauvaise chose à renvoyer List<T> et les classes dérivées de Collection<T> devraient être préférés comme types de retour.

Par ailleurs, FxCop indique qu'il est possible d'utiliser List<T> pour le stockage/la manipulation de données internes. Ok, j'ai compris, mais ce que je ne comprends pas, c'est pourquoi le compilateur se plaint d'essayer de convertir implicitement List<T> a Collection<T> . N'est-ce pas List<T> plus chargée d'interfaces et plus fonctionnelle ? Pourquoi interdire la conversion implicite ?

Et une autre question qui découle de ce qui précède : est-ce que le new List<int>(some collection<int>) Le constructeur est-il coûteux ?

106voto

Matthew M. Points 1585

Pourquoi ne pas faire ce qui suit ?

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

comme Collection(IList input) prend une liste comme élément de construction.

41voto

Jon Skeet Points 692016

List<T> ne découle pas de Collection<T> - il met toutefois en œuvre ICollection<T> . Ce serait un meilleur choix de type de retour.

En ce qui concerne les new List<int>(some collection<int>) question - cela dépend en partie de la nature de la collection. Si elle implémente ICollection<T> (au moment de l'exécution), le constructeur peut alors utiliser son Count pour créer la liste avec la bonne capacité initiale avant de la parcourir et d'ajouter chaque élément. S'il n'implémente pas la propriété ICollection<T> alors c'est juste équivalent à :

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

Il est toujours agréable d'avoir un constructeur pratique, mais il n'est pas extrêmement efficace - il ne peut pas l'être, en fait.

Je ne crois pas que le constructeur fasse quoi que ce soit d'astucieux pour les tableaux, ce qu'il pourrait potentiellement faire - en utilisant Array.Copy ou autre pour copier le tout 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 au tableau de soutien et le copier directement).

6voto

Voici une méthode d'extension générique écrite en C# 3.0 qui permet de convertir List<T> a 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 il est utilisé comme suit

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>();

6voto

David Morton Points 10519

List<T> n'hérite pas de Collection<T> . Tout simplement. A moins que List<T> fournit un opérateur permettant de convertir implicitement de/en 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 sont à peu près les suivantes :

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

0voto

Shadi Namrouti Points 1453

C'est ainsi que l'on passe de List<T> a Collection<T> (en utilisant 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 la 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>
           );
}

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