Cannot convert from an IEnumerable<T> to an ICollection<T>

C#.Net

C# Problem Overview


I have defined the following:

public ICollection<Item> Items { get; set; }

When I run this code:

Items = _item.Get("001");

I get the following message:

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?)

Can someone explain what I am doing wrong. I am very confused about the difference between Enumerable, Collections and using the ToList()

Added information

Later in my code I have the following:

for (var index = 0; index < Items.Count(); index++) 

Would I be okay to define Items as an IEnumerable?

C# Solutions


Solution 1 - C#

ICollection<T> inherits from IEnumerable<T> so to assign the result of

IEnumerable<T> Get(string pk)

to an ICollection<T> there are two ways.

// 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();

The second options is more flexible, but has a much larger performance impact. Another option is to store the result as an IEnumerable<T> unless you need the extra functionality added by the ICollection<T> interface.

Additional Performance Comment

The loop you have

for (var index = 0; index < Items.Count(); index++)

works on an IEnumerable<T> but it is inefficient; each call to Count() requires a complete enumeration of all elements. Either use a collection and the Count property (without the parenthesis) or convert it into a foreach loop:

foreach(var item in Items)

Solution 2 - C#

You cannot convert directly from IEnumerable<T> to ICollection<T>. You can use ToList method of IEnumerable<T> to convert it to ICollection<T>

someICollection = SomeIEnumerable.ToList();

Solution 3 - C#

Pending more information on the question:

please provide more information on the type of item and the signature of Get

Two things you can try are:

  • To cast the return value of _item.Get to (ICollection)
  • secondly to use _item.Get("001").ToArray() or _item.Get("001").ToList()

Please note the second will incur a performance hit for the array copy. If the signature (return type) of Get is not an ICollection then the first will not work, if it is not IEnumerable then the second will not work.


Following your clarification to question and in comments, I would personally declare the returning type of _item.Get("001") to ICollection. This means you won't have to do any casting or conversion (via ToList / ToArray) which would involve an unnecessary create/copy operation.

// 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++) 

Best regards,

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionSamantha J T StarView Question on Stackoverflow
Solution 1 - C#Anders AbelView Answer on Stackoverflow
Solution 2 - C#Haris HasanView Answer on Stackoverflow
Solution 3 - C#Dr. Andrew Burnett-ThompsonView Answer on Stackoverflow