Подтвердить что ты не робот

Невозможно неявно преобразовать List <T> в Collection <T>

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

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

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

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

Спасибо,

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

4b9b3361

Ответ 1

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>, он мог попасть в массив поддержки и скопировать его напрямую.)

Ответ 2

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

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

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

Ответ 3

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

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

Ответ 4

Вот общий метод расширения, написанный на С# 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>();

Ответ 5

Вот как вы конвертируете из 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>
           );
}

Ответ 6

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

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

      public EmployeeCollection() : base()
      {}

}

Используйте класс, подобный этому

EmployeeCollection  employeeCollection = new EmployeeCollection(list)