Skip to content

Latest commit

 

History

History
64 lines (46 loc) · 3.3 KB

LDM-2023-06-05.md

File metadata and controls

64 lines (46 loc) · 3.3 KB

C# Language Design Meeting for June 5th, 2023

Agenda

Quote of the Day

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.

Discussion

Collection literals

#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.

Conclusion

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.