IEnumerable to IReadOnlyCollection
One way would be to construct a list, and call AsReadOnly()
on it:
IReadOnlyCollection<Object> rdOnly = orig.ToList().AsReadOnly();
This produces ReadOnlyCollection<object>
, which implements IReadOnlyCollection<Object>
.
Note: Since List<T>
implements IReadOnlyCollection<T>
as well, the call to AsReadOnly()
is optional. Although it is possible to call your method with the result of ToList()
, I prefer using AsReadOnly()
, so that the readers of my code would see that the method that I am calling has no intention to modify my list. Of course they could find out the same thing by looking at the signature of the method that I am calling, but it is nice to be explicit about it.
As an alternative to dasblinkenlight's answer, to prevent the caller casting to List<T>, instead of doing orig.ToList().AsReadOnly()
, the following might be better:
ReadOnlyCollection<object> rdOnly = Array.AsReadOnly(orig.ToArray());
It's the same number of method calls, but one takes the other as a parameter instead of being called on the return value.
Since the other answers seem to steer in the direction of wrapping the collections in a truly read-only type, let me add this.
I have rarely, if ever, seen a situation where the caller is so scared that an IEnumerable<T>
-taking method might maliciously try to cast that IEnumerable<T>
back to a List
or other mutable type, and start mutating it. Cue organ music and evil laughter!
No. If the code you are working with is even remotely reasonable, then if it asks for a type that only has read functionality (IEnumerable<T>
, IReadOnlyCollection<T>
...), it will only read.
Use ToList()
and be done with it.
As a side note, if you are creating the method in question, it is generally best to ask for no more than an IEnumerable<T>
, indicating that you "just want a bunch of items to read". Whether or not you need its Count
or need to enumerate it multiple times is an implementation detail, and is certainly prone to change. If you need multiple enumeration, simply do this:
items = items as IReadOnlyCollection<T> ?? items.ToList(); // Avoid multiple enumeration
This keeps the responsibility where it belongs (as locally as possible) and the method signature clean.
When returning a bunch of items, on the other hand, I prefer to return an IReadOnlyCollection<T>
. Why? The goal is to give the caller something that fulfills reasonsable expectations - no more, no less. Those expectations are usually that the collection is materialized and that the Count
is known - precisely what IReadOnlyCollection<T>
provides (and a simple IEnumerable<T>
does not). By being no more specific than this, our contract matches expectations, and the method is still free to change the underlying collection. (In contrast, if a method returns a List<T>
, it makes me wonder what context there is that I should want to index into the list and mutate it... and the answer is usually "none".)