I would like to write something like this:
var d = new ImmutableDictionary<string, int> { { "a", 1 }, { "b", 2 } };
(using ImmutableDictionary
from System.Collections.Immutable). It seems like a straightforward usage as I am declaring all the values upfront -- no mutation there. But this gives me error:
The type '
System.Collections.Immutable.ImmutableDictionary<TKey,TValue>
' has no constructors defined
How I am supposed to create a new immutable dictionary with static content?
An ImmutableDictionary has methods to modify it like Add or Remove , but they will create a new dictionary and return that, the original one remains unchanged and the copy of the new immutable dictionary is returned.
If you need an immutable dictionary use ImmutableDictionary , which is just thread-safe as side-effect (if you can't modify the original instance there is no multi-threading issue).
ImmutableArray. Provides methods for creating an array that is immutable; meaning it cannot be changed once it is created. NuGet package: System.Collections.Immutable (about immutable collections and how to install)
Either create a "normal" dictionary first and call ToImmutableDictionary
(as per your own answer), or use ImmutableDictionary<,>.Builder
:
var builder = ImmutableDictionary.CreateBuilder<string, int>(); builder.Add("a", 1); builder.Add("b", 2); var result = builder.ToImmutable();
It's a shame that the builder doesn't have a public constructor as far as I can tell, as it prevents you from using the collection initializer syntax, unless I've missed something... the fact that the Add
method returns void
means you can't even chain calls to it, making it more annoying - as far as I can see, you basically can't use a builder to create an immutable dictionary in a single expression, which is very frustrating :(
You can't create immutable collection with a collection initializer because the compiler translates them into a sequence of calls to the Add
method. For example if you look at the IL code for var d = new Dictionary<string, int> { { "a", 1 }, { "b", 2 } };
you'll get
IL_0000: newobj instance void class [mscorlib]System.Collections.Generic.Dictionary`2<string, int32>::.ctor() IL_0005: dup IL_0006: ldstr "a" IL_000b: ldc.i4.1 IL_000c: callvirt instance void class [mscorlib]System.Collections.Generic.Dictionary`2<string, int32>::Add(!0, !1) IL_0011: dup IL_0012: ldstr "b" IL_0017: ldc.i4.2 IL_0018: callvirt instance void class [mscorlib]System.Collections.Generic.Dictionary`2<string, int32>::Add(!0, !1)
Obviously this violates the concept of immutable collections.
Both your own answer and Jon Skeet's are ways to deal with this.
// lukasLansky's solution var d = new Dictionary<string, int> { { "a", 1 }, { "b", 2 } }.ToImmutableDictionary(); // Jon Skeet's solution var builder = ImmutableDictionary.CreateBuilder<string, int>(); builder.Add("a", 1); builder.Add("b", 2); var result = builder.ToImmutable();
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With