Невозможно неявно преобразовать список <T>в коллекцию <T> - PullRequest
41 голосов
/ 07 февраля 2009

Это ошибка компилятора (немного изменена для удобства чтения).

Этот всегда меня озадачивал. FxCop говорит, что возвращать List - это плохо, и классы, которые являются производными от Collection<T>, должны быть предпочтительными в качестве возвращаемых типов.

Кроме того, FxCop говорит, что можно использовать List<T> для внутреннего хранения / манипулирования данными. Хорошо, я понимаю, но я не понимаю, что компилятор жалуется на попытку неявного преобразования List<T> в Collection<T>. Разве List<T> не более заряженный и функциональный интерфейс? Зачем запрещать неявное преобразование?

И еще один вопрос, который вытекает из вышесказанного: дорогой ли new List<int>(some collection<int>) конструктор?

Спасибо,

Валентин Васильев

Ответы [ 7 ]

90 голосов
/ 10 ноября 2009

Почему бы просто не сделать следующее:

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

as Collection (вход IList) принимает список как часть конструкции.

35 голосов
/ 07 февраля 2009

List<T> не является производным от Collection<T> - однако он реализует ICollection<T>. Это был бы лучший выбор типа возврата.

Что касается вопроса new List<int>(some collection<int>) - это частично зависит от того, что представляет собой коллекция. Если он реализует ICollection<T> (во время выполнения), тогда конструктор может использовать свое свойство Count для создания списка с правильной начальной емкостью, прежде чем выполнять итерацию по нему и добавлять каждый элемент. Если он не реализует ICollection<T>, то это просто эквивалентно:

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

По-прежнему приятно иметь удобный конструктор, но не очень эффективный - на самом деле этого не может быть.

Я не верю, что конструктор делает что-то хитрое для массивов, что он потенциально мог бы - используя Array.Copy или что-то еще, чтобы просто скопировать лот за один раз, а не выполнять итерации. (Аналогично, если бы это был другой List<T>, он мог бы получить в резервном массиве и скопировать его напрямую.)

6 голосов
/ 07 февраля 2009

List<T> не наследуется от Collection<T>. Легко и просто. Если List<T> не предоставляет оператора для неявного преобразования в / из Collection<T>, вы не сможете этого сделать. Я бы на самом деле предложил вернуть List<T>, если вы можете, так как я считаю, что правила идут примерно так:

Примите в качестве параметра наименьший возможный интерфейс. Вернуть в качестве возвращаемого параметра максимально возможный тип ограничения.

4 голосов
/ 09 июня 2009

Вот общий метод расширения, написанный на C # 3.0, который используется для преобразования List<T> в 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;
    }
}

и он используется вот так ...

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>();
0 голосов
/ 26 февраля 2019

Наоборот, не нужно зацикливаться ... вы можете сделать просто .ToList()

    ICollection<T> collection = new Collection<T>();

заполните свою коллекцию любым способом, и когда вам нужен список, просто сделайте это:

    List<T> list = collection.ToList();

после этого вы можете использовать в своем списке все, что захотите.

Удачного кодирования!

0 голосов
/ 22 июля 2015

Вы можете использовать ниже

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

      public EmployeeCollection() : base()
      {}

}

Используй класс вот так

EmployeeCollection  employeeCollection = new EmployeeCollection(list)
0 голосов
/ 24 мая 2015

Это способ конвертации List<T> в Collection<T> (при использовании LINQ):

Старая функция:

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

После преобразования:

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