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
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.)
Warum nicht einfach folgendes tun:
Collection<string> collection = new Collection<string>(theList);
as Collection (IList-Eingabe) übernimmt eine Liste als Teil der Konstruktion.
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.
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>();
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)
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>
);
}