8

The ReadOnlyCollection constructor requires that you give it IList. But if you have some ROC's that you want to concatenate and produce a new ROC, the Concat method returns IEnumerable. Which is not a valid argument to pass to the ROC constructor.

So how do you create a ROC as the concatenation of other ROC's?

So far, this is the best I can come up with:

ReadOnlyCollection<T> ROCConcat<T> ( ReadOnlyCollection<T> a, ReadOnlyCollection<T> b)
{
    List<T> tmp = new List<T>();
    foreach (T f in a.Concat(b))
        tmp.Add(f);
    return new ReadOnlyCollection<T>(tmp);
}
Edward Ned Harvey
  • 6,525
  • 5
  • 36
  • 45
  • Note that when you do this you break the link between the ROC and it's underlying `IList` so if the `IList` is modified (a item was added or removed from the list, I am not talking about items in the lists being modified) `a` and `b` would show the modification but your new concated collection would still show the original `IList`'s concated together. – Scott Chamberlain Jan 02 '14 at 20:16

2 Answers2

13

Create a new List<> out of your IEnumerable<>:

return new ReadOnlyCollection<T>(a.Concat(b).ToList());

Or I prefer:

return a.Concat(b).ToList().AsReadOnly();

These basically do the same thing as what you've come up with, but they're a little easier on the eyes.

StriplingWarrior
  • 151,543
  • 27
  • 246
  • 315
  • Ahh. So I was reinventing the ToList and AsReadOnly methods. But conceptually this is still the same. I guess creating intermediate list is not significant performance problem, so this is good enough. But if there's a way to do this without creating intermediate list, I would probably accept that other answer instead. – Edward Ned Harvey Jan 02 '14 at 20:18
  • @EdwardNedHarvey: That's correct. The key is to realize that `ReadOnlyCollection` is simply a wrapper around an existing list. That's why it's `AsReadOnly()` instead of `ToReadOnly()`. So the List itself is not an *intermediate* step--it is the structure that the `ReadOnlyCollection` is based on. `.Concat()` is cheap, `.ToList()` is expensive, and `.AsReadOnly()` is cheap. – StriplingWarrior Jan 02 '14 at 21:07
9

I believe you can use ReadOnlyCollectionBuilder to do this.

return (new ReadOnlyCollectionBuilder<T>(a.Concat(b))).ToReadOnlyCollection();
Brian Reischl
  • 7,216
  • 2
  • 35
  • 46