Невозможно преобразовать из IEnumerable <T> в ICollection <T>
Я определил следующее:
public ICollection<Item> Items { get; set; }
Когда я запускаю этот код:
Items = _item.Get("001");
Получаю следующее сообщение:
Error 3
Cannot implicitly convert type
'System.Collections.Generic.IEnumerable<Storage.Models.Item>' to
'System.Collections.Generic.ICollection<Storage.Models.Item>'.
An explicit conversion exists (are you missing a cast?)
Может кто-нибудь объяснить, что я делаю неправильно. Я очень смущен
разница между Enumerable, Collections и использование ToList()
Добавленная информация
Позже в моем коде у меня есть следующее:
for (var index = 0; index < Items.Count(); index++)
Можно ли определить элементы как IEnumerable?
Ответы
Ответ 1
ICollection<T>
наследует от IEnumerable<T>
так, чтобы назначить результат
IEnumerable<T> Get(string pk)
до ICollection<T>
существует два пути.
// 1. You know that the referenced object implements `ICollection<T>`,
// so you can use a cast
ICollection<T> c = (ICollection<T>)Get("pk");
// 2. The returned object can be any `IEnumerable<T>`, so you need to
// enumerate it and put it into something implementing `ICollection<T>`.
// The easiest is to use `ToList()`:
ICollection<T> c = Get("pk").ToList();
Второй вариант более гибкий, но имеет гораздо большее влияние на производительность. Другой вариант - сохранить результат как IEnumerable<T>
, если вам не нужна дополнительная функциональность, добавленная интерфейсом ICollection<T>
.
Комментарий к дополнительной производительности
В цикле у вас
for (var index = 0; index < Items.Count(); index++)
работает с IEnumerable<T>
, но неэффективен; каждый вызов Count()
требует полного перечисления всех элементов. Либо используйте коллекцию и свойство Count
(без скобок), либо преобразуйте их в цикл foreach:
foreach(var item in Items)
Ответ 2
Вы не можете преобразовать непосредственно из IEnumerable<T>
в ICollection<T>
. Вы можете использовать ToList
метод IEnumerable<T>
, чтобы преобразовать его в ICollection<T>
someICollection = SomeIEnumerable.ToList();
Ответ 3
В ожидании дополнительной информации по вопросу:
просьба предоставить дополнительную информацию о типе элемента и подписи Get
Две вещи, которые вы можете попробовать:
- Чтобы вернуть возвращаемое значение _item.Get to (ICollection)
- во-вторых, использовать _item.Get( "001" ). ToArray() или _item.Get( "001" ). ToList()
Обратите внимание, что вторая приведет к удару производительности для копии массива. Если подпись (тип возврата) Get не является ICollection, то первая не будет работать, если она не IEnumerable, то вторая не будет работать.
После разъяснения вопроса и комментариев я лично объявляю возвращаемый тип _item.Get( "001" ) в ICollection. Это означает, что вам не нужно делать кастинг или преобразование (через ToList/ToArray), что потребует ненужной операции создания/копирования.
// Leave this the same
public ICollection<Item> Items { get; set; }
// Change function signature here:
// As you mention Item uses the same underlying type, just return an ICollection<T>
public ICollection<Item> Get(string value);
// Ideally here you want to call .Count on the collectoin, not .Count() on
// IEnumerable, as this will result in a new Enumerator being created
// per loop iteration
for (var index = 0; index < Items.Count(); index++)
С уважением,