, FuncOfT wrote

At what point did someone finally say, "this is important" and why?  Have things changed so much in the past 11 years, that immutable collections became obviously important, or was there technical reasons for not creating these libraries?  Was it a matter of expedience, or was the theory still fresh out of the ivory tower, and just not recognized as important by anyone but the academics?

The main reason is that if you know something is immutable then you know certain classes of actions on that collection can be done without doing something bad.

For example, if foo is a mutable collection, you can prove that DoSomething has no IO side-effects, and you see the code

for(int i = 0; i < foo.Count; i++) DoSomething(foo[i])

Can the compiler automatically convert that into the following?

Parallel.For(0, foo.Count, (i) => DoSomething(foo[i]));

Or even more crazy:

DistributeWorkOverDifferentAzureProcessors.For(0, foo.Count, (i) => DoSomething(foo[i]))

Immutability is much more powerful than just being a cheap way of easily preventing naughty callers from changing the private collections owned by your class - they are a property of the collection that allows either a human or a machine to make fundamental changes to the code such as making the collection more suited to O(1) storage and retrieval from some of MSR's experimental databases, automatic parallelization of code not just to other threads within a machine, but to other processors that are completely removed from your machine.

Although we've had compute clusters and parallelization for a while now, we're only just starting to get to the point where languages are taking the brunt of the complexity, and one of the ways of getting to where we need to be is to have more descriptive and better annotated types in the language, such as being able to mark objects as immutable.

For that reason, Immutable collections are only just becoming important enough to warrant space in the base libraries of .NET. Back when immutability was only for protecting private members you could just have written a wrapper MutableList<T> : List<T> { override void Add() { throw; } }, so it was less important to have fast and inbuilt types to manage the immutability.