Невозможно неявно преобразовать List <T> в Collection <T>
Это ошибка компилятора (слегка измененная для удобочитаемости).
Это всегда меня озадачивало. FxCop сообщает, что это плохо, чтобы возвращать List и классы, которые являются\производными от Collection<T>
, должны быть предпочтительными в качестве типов возврата.
Кроме того, FxCop говорит, что использовать List<T>
для внутреннего хранения данных \use.
Хорошо, я понял, но я не понимаю, что компилятор жалуется на попытку неявно преобразовать List<T>
в Collection<T>
. Является ли List<T>
более функциональным и функциональным?
Зачем запрещать неявное преобразование?
И еще один вопрос, который возникает выше: конструктор new List<int>(some collection<int>)
дорогой?
Спасибо,
Валентин Васильев
Ответы
Ответ 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)