-
Notifications
You must be signed in to change notification settings - Fork 5.2k
Add FrozenDictionary.Create #114192
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add FrozenDictionary.Create #114192
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,22 @@ | ||
| <?xml version="1.0" encoding="utf-8"?> | ||
| <!-- https://learn.microsoft.com/dotnet/fundamentals/package-validation/diagnostic-ids --> | ||
| <Suppressions xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> | ||
| <Suppression> | ||
| <DiagnosticId>CP0016</DiagnosticId> | ||
| <Target>T:System.Collections.Frozen.FrozenDictionary`2:[T:System.Runtime.CompilerServices.CollectionBuilderAttribute]</Target> | ||
| <Left>ref/net10.0/System.Collections.Immutable.dll</Left> | ||
| <Right>lib/net10.0/System.Collections.Immutable.dll</Right> | ||
| </Suppression> | ||
| <Suppression> | ||
| <DiagnosticId>CP0016</DiagnosticId> | ||
| <Target>T:System.Collections.Frozen.FrozenDictionary`2:[T:System.Runtime.CompilerServices.CollectionBuilderAttribute]</Target> | ||
| <Left>ref/net8.0/System.Collections.Immutable.dll</Left> | ||
| <Right>lib/net8.0/System.Collections.Immutable.dll</Right> | ||
| </Suppression> | ||
| <Suppression> | ||
| <DiagnosticId>CP0016</DiagnosticId> | ||
| <Target>T:System.Collections.Frozen.FrozenDictionary`2:[T:System.Runtime.CompilerServices.CollectionBuilderAttribute]</Target> | ||
| <Left>ref/net9.0/System.Collections.Immutable.dll</Left> | ||
| <Right>lib/net9.0/System.Collections.Immutable.dll</Right> | ||
| </Suppression> | ||
| </Suppressions> |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -16,6 +16,50 @@ namespace System.Collections.Frozen | |
| /// </summary> | ||
| public static class FrozenDictionary | ||
| { | ||
| /// <summary>Creates a <see cref="FrozenDictionary{TKey, TValue}"/> with the specified key/value pairs.</summary> | ||
| /// <param name="source">The key/value pairs to use to populate the dictionary.</param> | ||
| /// <typeparam name="TKey">The type of the keys in the dictionary.</typeparam> | ||
| /// <typeparam name="TValue">The type of the values in the dictionary.</typeparam> | ||
| /// <remarks> | ||
| /// If the same key appears multiple times in the input, the latter one in the sequence takes precedence. This differs from | ||
| /// <see cref="M:System.Linq.Enumerable.ToDictionary"/>, with which multiple duplicate keys will result in an exception. | ||
| /// </remarks> | ||
| /// <returns>A <see cref="FrozenDictionary{TKey, TValue}"/> that contains the specified keys and values.</returns> | ||
| public static FrozenDictionary<TKey, TValue> Create<TKey, TValue>(params ReadOnlySpan<KeyValuePair<TKey, TValue>> source) | ||
| where TKey : notnull => | ||
| Create(null, source); | ||
|
|
||
| /// <summary>Creates a <see cref="FrozenDictionary{TKey, TValue}"/> with the specified key/value pairs.</summary> | ||
| /// <param name="source">The key/value pairs to use to populate the dictionary.</param> | ||
| /// <param name="comparer">The comparer implementation to use to compare keys for equality. If <see langword="null"/>, <see cref="EqualityComparer{TKey}.Default"/> is used.</param> | ||
| /// <typeparam name="TKey">The type of the keys in the dictionary.</typeparam> | ||
| /// <typeparam name="TValue">The type of the values in the dictionary.</typeparam> | ||
| /// <remarks> | ||
| /// If the same key appears multiple times in the input, the latter one in the sequence takes precedence. This differs from | ||
| /// <see cref="M:System.Linq.Enumerable.ToDictionary"/>, with which multiple duplicate keys will result in an exception. | ||
| /// </remarks> | ||
| /// <returns>A <see cref="FrozenDictionary{TKey, TValue}"/> that contains the specified keys and values.</returns> | ||
| public static FrozenDictionary<TKey, TValue> Create<TKey, TValue>(IEqualityComparer<TKey>? comparer, params ReadOnlySpan<KeyValuePair<TKey, TValue>> source) | ||
| where TKey : notnull | ||
| { | ||
| comparer ??= EqualityComparer<TKey>.Default; | ||
|
|
||
| if (source.IsEmpty) | ||
| { | ||
| return ReferenceEquals(comparer, FrozenDictionary<TKey, TValue>.Empty.Comparer) ? | ||
| FrozenDictionary<TKey, TValue>.Empty : | ||
| new EmptyFrozenDictionary<TKey, TValue>(comparer); | ||
| } | ||
|
|
||
| Dictionary<TKey, TValue> d = new(source.Length, comparer); | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Out of curiosity (out of scope for this PR), would it be possible to optimize the construction of frozen dictionaries from constant collections (as in, a collection expressions where all keys are compile time constants) so to avoid building the intermedia dictionary, and perhaps just enable some additional fast-path during construction? Would something like that be more like something that eg. ILC could do on NAOT, or something that Roslyn/.NET could improve in general? I'm asking because we have a scenario in CsWinRT where we'd end up with a massive lookup table of
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Internals of dotnet/runtime repo also come across similar requirements in areas like formats, globalization and security, we ended up source generating blittable RVA data fields with chain of switch-cases (and in some places without switch-cases using multiple ROS). An example of such generator which packs the lookup table in data section: sharplab (fill |
||
| foreach (KeyValuePair<TKey, TValue> pair in source) | ||
| { | ||
| d[pair.Key] = pair.Value; | ||
| } | ||
|
|
||
| return CreateFromDictionary(d); | ||
| } | ||
|
|
||
| /// <summary>Creates a <see cref="FrozenDictionary{TKey, TValue}"/> with the specified key/value pairs.</summary> | ||
| /// <param name="source">The key/value pairs to use to populate the dictionary.</param> | ||
| /// <param name="comparer">The comparer implementation to use to compare keys for equality. If null, <see cref="EqualityComparer{TKey}.Default"/> is used.</param> | ||
|
|
@@ -259,6 +303,7 @@ private static FrozenDictionary<TKey, TValue> CreateFromDictionary<TKey, TValue> | |
| /// the remainder of the life of the application. <see cref="FrozenDictionary{TKey, TValue}"/> should only be | ||
| /// initialized with trusted keys, as the details of the keys impacts construction time. | ||
| /// </remarks> | ||
| [CollectionBuilder(typeof(FrozenDictionary), nameof(FrozenDictionary.Create))] | ||
| [DebuggerTypeProxy(typeof(ImmutableDictionaryDebuggerProxy<,>))] | ||
| [DebuggerDisplay("Count = {Count}")] | ||
| public abstract partial class FrozenDictionary<TKey, TValue> : IDictionary<TKey, TValue>, IReadOnlyDictionary<TKey, TValue>, IDictionary | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.