5

The ToReadOnlyCollection extension method is implemented with a shortcut statement to return the input directly if it is already an instance of ReadOnlyCollection. The ToList extension method isnt.

Purely out of curiosity, is there a particular reason for this, or just something that happens not to have been implemented. I can see why guaranteeing that ToList will always return a new instance might be useful, but id be interested to know if theres any other reason.

richzilla
  • 40,440
  • 14
  • 56
  • 86
  • [Related](http://stackoverflow.com/questions/2774099/tolist-does-it-create-a-new-list) - see the [answer by LBushkin](http://stackoverflow.com/a/2774120/791010) – James Thorpe Feb 23 '15 at 11:49

2 Answers2

13

A read only collection can't be modified so it is perfectly acceptable to return the same instance as a result of .ToReadOnlyCollection().

If the result of a .ToList() operation sometimes returned a new list and sometimes didn't you wouldn't know if you're modifying the source list when changing the output list. So, for this reason, .ToList() always returns a new instance.

Enigmativity
  • 113,464
  • 11
  • 89
  • 172
  • Well one could use some kind of "fork" mechanism with an observer pattern that could make real copies if the original changed. But that would probably be way less efficient. – Willem Van Onsem Feb 23 '15 at 11:59
2

That's reasonable. Since it is possible you will alter the List<T> later in the process, you need to make a copy of the original List<T>.

You could think of postponing the process until you alter a value of the created list. Note however it is possible that you will alter the first list first.

Example:

List<String> first = new List<String>(new string[] {"foo","bar"});
List<String> second = first.ToList();
first[0] = "qux";

Now it is very hard to make sure that in that case the copy is made before altering the list. Furthermore it would be less efficient since each time a value is updated, one should first check if there are lazy copies and in that case start copying. Furthermore it could result in a burst/bubble: a large amount of work to be carried out that is eventually done after modifying a single value could result in a huge delay. Imagine that you are running a server where people "fork" a popular list. Eventually that list is indeed modified. It could result in the fact that the user will wait for minutes because the server starts making copies for all people that forked that list in the first place. It's better to spread computation over time such that the variance over delay is smaller.

The case of a .ToReadOnlyCollection is different. In that case you define a wrapper around the original list. In case you modify the original list, that change is reflected in the read-only collection as well. So you can link to the previous list. For instance:

$ csharp
Mono C# Shell, type "help;" for help

Enter statements below.
csharp> List<String> first = new List<String>(new string[] {"foo","bar"});
csharp> var sec = first.AsReadOnly();         
csharp> sec
{ "foo", "bar" }
csharp> first[0] = "qux";
csharp> sec               
{ "qux", "bar" }
Willem Van Onsem
  • 443,496
  • 30
  • 428
  • 555