Reputation: 1315
I can't seem to figure out how add items to an ImmutableList
inside of an ImmutableDictionary
.
I have the following variable:
ImmutableDictionary<string, ImmutableList<string>> _attributes = ImmutableDictionary<string, ImmutableList<string>>.Empty;
To which I'm trying to add a value inside of the list:
string[] attribute = line.Split(':');
if (!_attributes.ContainsKey(attribute[0]))
_attributes = _attributes.Add(attribute[0], ImmutableList<string>.Empty);
if (attribute.Length == 2)
_attributes[attribute[0]] = _attributes[attribute[0]].Add(attribute[1]);
However, I get an error saying that the ImmutableList
doesn't have a setter. How do I replace the list in the dictionary without having to rebuilt the entire Dictionary?
Upvotes: 4
Views: 1337
Reputation: 44026
You could use the ImmutableDictionary.TryGetValue
method, in order to reduce the dictionary lookups from 3 to 2.
var _attributes = ImmutableDictionary.Create<string, ImmutableList<string>>();
string[] parts = line.Split(':');
if (parts.Length == 2)
{
string attributeName = parts[0];
string attributeValue = parts[1];
if (_attributes.TryGetValue(attributeName, out var list))
{
_attributes = _attributes.SetItem(attributeName, list.Add(attributeValue));
}
else
{
_attributes = _attributes.Add(attributeName, ImmutableList.Create(attributeValue));
}
}
In case you wanted to update the dictionary with thread-safety as an atomic operation, you could use the ImmutableInterlocked.AddOrUpdate
method:
ImmutableInterlocked.AddOrUpdate(ref _attributes, attributeName,
_ => ImmutableList.Create(attributeValue),
(_, existing) => existing.Add(attributeValue));
Upvotes: 1
Reputation: 22848
The ImmutableCollections provide a bunch of different ways how you can construct them.
The general guidance is first populate them then make them immutable.
Create
+ AddRange
ImmutableDictionary<string, string> collection1 = ImmutableDictionary
.Create<string, string>(StringComparer.InvariantCultureIgnoreCase)
.AddRange(
new[]
{
new KeyValuePair<string, string>("a", "a"),
new KeyValuePair<string, string>("b", "b"),
});
We have created an empty collection then created another one with some values.
Create
+ Builder
ImmutableDictionary<string, string>.Builder builder2 = ImmutableDictionary
.Create<string, string>(StringComparer.InvariantCultureIgnoreCase)
.ToBuilder();
builder2.AddRange(
new[]
{
new KeyValuePair<string, string>("a", "a"),
new KeyValuePair<string, string>("b", "b"),
});
ImmutableDictionary<string, string> collection2 = builder2.ToImmutable();
We have created an empty collection then converted it to a builder.
We have populated it with values.
Finally we have constructed the immutable collection.
CreateBuilder
ImmutableDictionary<string, string>.Builder builder3 = ImmutableDictionary
.CreateBuilder<string, string>(StringComparer.InvariantCultureIgnoreCase);
builder3
.AddRange(
new[]
{
new KeyValuePair<string, string>("a", "a"),
new KeyValuePair<string, string>("b", "b"),
});
ImmutableDictionary<string, string> collection3 = builder3.ToImmutable();
This is short form of the previous case (Create
+ ToBuilder
)
CreateRange
ImmutableDictionary<string, string> collection4 = ImmutableDictionary
.CreateRange(new[]
{
new KeyValuePair<string, string>("a", "a"),
new KeyValuePair<string, string>("b", "b"),
});
This is short form of the first case (Create
+ AddRange
)
ToImmutableDictionary
ImmutableDictionary<string, string> collection5 = new Dictionary<string, string>
{
{ "a", "a" },
{ "b", "b" }
}.ToImmutableDictionary();
Last but not least here we have used a converter.
Upvotes: 6