4

What is the recommended way to cast an ICollection<Bar> to ICollection<IBar> where Bar implements IBar?

Is it as simple as

collection = new List<Bar>();
ICollection<IBar> = collection as ICollection<IBar>?

or is there a better way of doing it?

Mykola
  • 3,343
  • 6
  • 23
  • 39
Graham
  • 1,497
  • 2
  • 16
  • 36
  • 1
    It's not quite an exact duplicate, but read https://stackoverflow.com/questions/13107071 to see why your solution won't work. (It has syntax errors already, but even if it didn't, it would give `null` as a result of the `as` operator.) – Jon Skeet Jan 18 '16 at 15:04
  • 2
    You cannot cast to `ICollection`, but you can cast to `IEnumerable`. – Henrik Jan 18 '16 at 15:24
  • @HenkHolterman yes, thank you. I see now that none of the other answers mention this possibility. – Henrik Jan 19 '16 at 10:53

3 Answers3

3

You have to cast every item in the list and create a new one, for example with Cast:

ICollection<IBar> ibarColl = collection.Cast<IBar>().ToList();

In .NET 4, using the covariance of IEnumerable<T>:

ICollection<IBar> ibarColl = collection.ToList<IBar>();

or with List.ConvertAll:

ICollection<IBar> ibarColl = collection.ConvertAll(b => (IBar)b);

The latter might be a little bit more efficient since it knows the size beforehand.

Tim Schmelter
  • 450,073
  • 74
  • 686
  • 939
  • That would create a copy of the original list. Is there a way to reuse the same `ICollection` instance to add items and manipulate the collection? – Shimmy Weitzhandler Dec 15 '18 at 15:58
  • @Shimmy only if it's an instance of IList like an array or list. Then you can use a for loop and replace them or use Array.ConvertAll or list.ConvertAll as shown in the answer – Tim Schmelter Dec 15 '18 at 16:25
2

You cannot cast to ICollection<IBar>, but you can cast to IEnumerable<IBar>.

So if you don't intend to add something to the list, you can do this:

IEnumerable<IBar> enumeration = (IEnumerable<IBar>)collection;

The solutions from the other answers don't actually cast but create a new list that will not reflect subsequent changes to the original list.

Henrik
  • 23,186
  • 6
  • 42
  • 92
0

Just convert all entries with

ICollection<IBar> ibars = collection.ConvertAll(bar => (IBar)bar);

I think this variant is also readable. Perhaps there are ways to cast it with more performance...

Matthias Burger
  • 5,549
  • 7
  • 49
  • 94