Due to an unfortunate notekeeping snafu, there are no records of funny things said today. They did exist, but they are lost to the annals of time.
#5354
https://github.com/dotnet/csharplang/blob/main/meetings/working-groups/collection-literals/CL-LDM-2023-05-31.md
Today we continued our review of the work the collection literals working group has been doing, this time looking at dictionary creation patterns. We first thought about syntax, and the potential for ambiguous syntax. For example, this expresson would be ambiguous:
Dictionary<K, V> d = [a ? [b] : c]; // [a ? ([b]) : c)] or [(a ? [b]) : c]?
There was also a question raised whether it might be useful to state from the literal itself whether it would be a dictionary or a sequence. For example,
[..dictionary1, ..dictionary2]
might want to prefer combining into a new dictionary, not a sequence of elements. To try and address these cases, we
explored whether there was some alternative syntaxes that would mark the literal as a dictionary literal and force dictionary semantics.
[: a ? [b] : c]
- Leading:
[: a ? [b] : c :]
- Leading and trailing:
{ a ? [b] : c }
- Use{}
for dictionary literals
None of these particularly resonated with the LDM. Further, no language that we can find that has dictionary literals differentiates them from collection
literals with an extra or different sigil, so there's no prior art to draw on. Given this, we don't think there needs to be a separate syntax for
dictionary literals, and [..dictionary1, ..dictionary2]
will have sequence semantics unless target-typed to a dictionary type (including dictionary
interfaces such as IDictionary<TKey, TValue>
), or unless the literal contains a key : value
element.
Next, we thought about what semantics spreading dictionaries should have, when the literal will have dictionary semantics. For example, what would the following code print?
using System;
using System.Collections.Generic;
Dictionary<int, int> dictionary1 = [1 : 2];
Dictionary<int, int> dictionary2 = [1 : 3];
M([..dictionary1, ..dictionary2]);
void M(Dictionary<int, int> d)
{
foreach (var (k, v) in d) Console.WriteLine($"{k} {v}");
}
There are two possible behaviors: add behavior, where duplicate keys are error, or overwrite behavior, where the last instance of a key wins. There's two
competing schools of thought here. In favor of add behavior, most of our existing methods have this behavior. CreateRange
, the Dictionary
constructor,
collection initializers as they exist today, etc. However, [a : b]
looks more like an indexer, which does have overwrite semantics today. There also some
concern that, as we borrow this syntax from other languages, deviating too much from their behavior will introduce a quirk that is more gotcha than it is
helpful. Ultimately, we think that we should prefer overwrite semantics for this scenario.
No special syntax for differentiating a dictionary literal beyond the key : value
syntax for an individual element.
Dictionary literals will use overwrite semantics, not add semantics.