it-swarm.com.de

Die Liste <T> kann nicht implizit in die Sammlung <T> konvertiert werden

Dies ist ein Compiler-Fehler (zur besseren Lesbarkeit leicht geändert).

Dieser hat mich immer verwirrt. FxCop sagt, dass dies eine schlechte Sache ist, zurückzugeben. Liste und Klassen, die von Collection<T> abgeleitet sind, sollten als Rückgabetypen bevorzugt werden.

Außerdem sagt FxCop, dass es in Ordnung ist, List<T> für interne Datenspeicherung\Manipulation zu verwenden. Ok, ich verstehe, aber was ich nicht verstehe, ist, dass sich der Compiler beschwert, List<T> implizit in Collection<T> zu konvertieren. Ist List<T> nicht schnittstellenaufgeladen und funktionsfähig? Warum implizite Konvertierung untersagen?

Und noch eine Frage, die von oben kommt: Ist new List<int>(some collection<int>) constructor teuer?

Vielen Dank,

Valentin Vasiliev 

40
Valentin

List<T> leitet sich nicht von Collection<T> ab, sondern implementiert ICollection<T>. Das wäre eine bessere Wahl für die Rückgabe.

Was die new List<int>(some collection<int>)-Frage angeht, hängt es zum Teil von der Sammlung ab. Wenn ICollection<T> (zur Ausführungszeit) implementiert wird, kann der Konstruktor seine Count -Eigenschaft verwenden, um die Liste mit der richtigen Anfangskapazität zu erstellen, bevor er sie durchläuft und jedes Element hinzufügt. Wenn es ICollection<T> nicht implementiert, ist es nur gleichbedeutend mit:

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

Immer noch schön in einem praktischen Konstruktor zu haben, aber nicht besonders effizient - das kann nicht wirklich sein.

Ich glaube nicht, dass der Konstruktor etwas Listiges für Arrays tut, was er möglicherweise tun könnte - mit Array.Copy oder was auch immer, um die Menge in einem Durchgang zu kopieren und nicht zu iterieren. (Wenn es sich ebenfalls um einen anderen List<T> handeln würde, könnte er das unterstützende Array erhalten und dieses direkt kopieren.)

35
Jon Skeet

Warum nicht einfach folgendes tun:

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

as Collection (IList-Eingabe) übernimmt eine Liste als Teil der Konstruktion.

89
Matthew M.

List<T> erbt nicht von Collection<T>. Schlicht und einfach. Wenn List<T> keinen Operator für die implizite Konvertierung nach/von Collection<T> bereitstellt, ist dies nicht möglich. Ich würde tatsächlich vorschlagen, List<T> zurückzugeben, wenn Sie können, da ich glaube, dass die Regeln in etwa wie folgt aussehen:

Akzeptieren Sie als Parameter die am wenigsten einschränkende Schnittstelle. Rückgabe des einschränkenden Typs als Rückgabeparameter. 

6
David Morton

Hier ist eine generische Erweiterungsmethode in C # 3.0, die zum Konvertieren von List<T> in Collection<T> verwendet wird

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;
    }
}

und es wird so verwendet…

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

Sie können das folgende verwenden 

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

      public EmployeeCollection() : base()
      {}

}

Verwenden Sie die Klasse so

EmployeeCollection  employeeCollection = new EmployeeCollection(list)
0

So konvertieren Sie von List<T> zu Collection<T> (bei Verwendung von LINQ):

Die alte Funktion:

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

Nach der Konvertierung:

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