IEnumerable to IReadOnlyCollection
Solution 1
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.
Solution 2
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".)
Solution 3
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.
Related videos on Youtube
Mohamed Badr
Developer who like coding,coding and coding. for me programming is a life not only way to earn living best moments ever for me starting new service or web application
Updated on August 01, 2022Comments
-
Mohamed Badr almost 2 years
I have
IEnumerable<Object>
and need to pass to a method as a parameter but this method takesIReadOnlyCollection<Object>
Is it possible to convert
IEnumerable<Object>
toIReadOnlyCollection<Object>
? -
Scott Chamberlain over 8 years
.AsReadOnly()
does have its uses. If you just returnList<T>
someone can do ardOnly is IList<T>
and it will returntrue
, if you do.AsReadOnly()
it will returnfalse
. If I don't know if my consumer could potentially try to cast my result in to a mutable interface I often do a.AsReadOnly()
before I return the result. -
florien over 5 years@ScottChamberlain this is a very important security feature to mention!
-
florien over 5 yearsThis might even be faster!
-
Soner from The Ottoman Empire over 4 years@florien why might it even faster? Could you explain?
-
florien over 4 years@snr Well, to be honest, I could not back it with a reasonable explanation. Somehow I believe that here, where the only difference is whether the type is first converted to an array or a list, arrays and working with them is more integrated into the language, and since the collection is not to be changed, list has no advantage here. Though it can indeed be that this all is optimised by the compiler.
-
Mass Dot Net over 3 yearsCould you call
.ToArray()
instead of.ToList().AsReadOnly()
? -
Sergey Kalinichenko over 3 years@MassDotNet You could, because arrays implement
IReadOnlyCollection<T>
. -
Mass Dot Net over 3 yearsThought so -- that's what I'm already doing. I just wanted to make sure there wasn't any errant behavior invited by doing so (e.g. screwing up sort order).
-
Benjamin Salerno over 2 yearsIs there a way to do this the opposite? Convert IReadOnlyCollection to IEnumerable?
-
Sergey Kalinichenko over 2 years@BenjaminSalerno
IReadOnlyCollection<T>
is anIEnumerable<T>
, so you can plug it into any place where anIEnumerable<T>
is needed.