Skip to content

Commit

Permalink
Fix a variety of issues in FrozenCollections
Browse files Browse the repository at this point in the history
- Add the new ToFrozenDictionary/Set methods that take optimizedForReading and make the existing overloads cheaper for construction.  This makes construction time and allocation by default much closer to that of a normal dictionary or set while also enabling more of the implementation to be trimmed away by default.
- Fixed the use of FrozenSet/Dictionary.Empty such that we only use the singleton when its comparer matches; otherwise, we could end up handing back an instance with the wrong comparer.
- Avoided passing both a dictionary/set and a comparer down through constructors, as the dictionary/set contains the comparer and we don't want to accidentally end up in a situation where we pass through the wrong one.
- Condensed some of the construction code to be a bit less verbose
- Removed unused locals from ToFrozenDictionary (the min/max/range were no longer being used)
- Remove unnecessary array allocations from PickIntegerDictionary
- Delete the sparse range integer sets, which are rarely needed and are broken for TryGetValue
- Fix CheckUniqueAndUnfoundElements to slice down to only the relevant size prior to clearing
  • Loading branch information
stephentoub committed Jan 26, 2023
1 parent f54716d commit 53412f1
Show file tree
Hide file tree
Showing 32 changed files with 950 additions and 791 deletions.
Expand Up @@ -9,6 +9,7 @@ namespace System.Collections.Frozen
public static partial class FrozenDictionary
{
public static System.Collections.Frozen.FrozenDictionary<TKey, TValue> ToFrozenDictionary<TKey, TValue>(this System.Collections.Generic.IEnumerable<System.Collections.Generic.KeyValuePair<TKey, TValue>> source, System.Collections.Generic.IEqualityComparer<TKey>? comparer = null) where TKey : notnull { throw null; }
public static System.Collections.Frozen.FrozenDictionary<TKey, TValue> ToFrozenDictionary<TKey, TValue>(this System.Collections.Generic.IEnumerable<System.Collections.Generic.KeyValuePair<TKey, TValue>> source, System.Collections.Generic.IEqualityComparer<TKey>? comparer, bool optimizeForReading) where TKey : notnull { throw null; }
public static System.Collections.Frozen.FrozenDictionary<TKey, TSource> ToFrozenDictionary<TSource, TKey>(this System.Collections.Generic.IEnumerable<TSource> source, System.Func<TSource, TKey> keySelector, System.Collections.Generic.IEqualityComparer<TKey>? comparer = null) where TKey : notnull { throw null; }
public static System.Collections.Frozen.FrozenDictionary<TKey, TElement> ToFrozenDictionary<TSource, TKey, TElement>(this System.Collections.Generic.IEnumerable<TSource> source, System.Func<TSource, TKey> keySelector, System.Func<TSource, TElement> elementSelector, System.Collections.Generic.IEqualityComparer<TKey>? comparer = null) where TKey : notnull { throw null; }
}
Expand Down Expand Up @@ -71,6 +72,7 @@ public partial struct Enumerator : System.Collections.Generic.IEnumerator<System
public static partial class FrozenSet
{
public static System.Collections.Frozen.FrozenSet<T> ToFrozenSet<T>(this System.Collections.Generic.IEnumerable<T> source, System.Collections.Generic.IEqualityComparer<T>? comparer = null) { throw null; }
public static System.Collections.Frozen.FrozenSet<T> ToFrozenSet<T>(this System.Collections.Generic.IEnumerable<T> source, System.Collections.Generic.IEqualityComparer<T>? comparer, bool optimizeForReading) { throw null; }
}
public abstract partial class FrozenSet<T> : System.Collections.Generic.ICollection<T>, System.Collections.Generic.IEnumerable<T>, System.Collections.Generic.IReadOnlyCollection<T>, System.Collections.Generic.ISet<T>, System.Collections.ICollection, System.Collections.IEnumerable
{
Expand Down
Expand Up @@ -10,6 +10,7 @@ The System.Collections.Immutable library is built-in as part of the shared frame

<ItemGroup>
<Compile Include="Properties\InternalsVisibleTo.cs" />

<Compile Include="System\Collections\Frozen\String\KeyAnalyzer.cs" />
<Compile Include="System\Collections\Frozen\String\OrdinalStringFrozenDictionary_FullCaseInsensitiveAscii.cs" />
<Compile Include="System\Collections\Frozen\String\OrdinalStringFrozenDictionary_FullCaseInsensitive.cs" />
Expand Down Expand Up @@ -142,18 +143,18 @@ The System.Collections.Immutable library is built-in as part of the shared frame
<None Include="Interfaces.cd" />
</ItemGroup>

<ItemGroup Condition="$([MSBuild]::IsTargetFrameworkCompatible('$(TargetFramework)', 'net6.0'))">
<Compile Include="System\Collections\Frozen\WrappedDictionaryFrozenDictionary.cs" />
</ItemGroup>

<ItemGroup Condition="$([MSBuild]::IsTargetFrameworkCompatible('$(TargetFramework)', 'net7.0'))">
<Compile Include="System\Collections\Frozen\Integer\IntegerFrozenDictionary.cs" />
<Compile Include="System\Collections\Frozen\Integer\IntegerFrozenSet.cs" />
<Compile Include="System\Collections\Frozen\Integer\SmallIntegerFrozenDictionary.cs" />
<Compile Include="System\Collections\Frozen\Integer\SmallIntegerFrozenSet.cs" />
<Compile Include="System\Collections\Frozen\Integer\SparseRangeIntegerFrozenSet.cs" />
</ItemGroup>

<ItemGroup Condition="!$([MSBuild]::IsTargetFrameworkCompatible('$(TargetFramework)', 'net7.0'))">
<Compile Include="System\Collections\Frozen\Int32\SmallInt32FrozenDictionary.cs" />
<Compile Include="System\Collections\Frozen\Int32\SmallInt32FrozenSet.cs" />
<Compile Include="System\Collections\Frozen\Int32\SparseRangeInt32FrozenSet.cs" />
</ItemGroup>

<ItemGroup Condition="'$(TargetFramework)' == '$(NetCoreAppCurrent)'">
Expand Down
Expand Up @@ -12,8 +12,8 @@ namespace System.Collections.Frozen
internal sealed class DefaultFrozenDictionary<TKey, TValue> : KeysAndValuesFrozenDictionary<TKey, TValue>, IDictionary<TKey, TValue>
where TKey : notnull
{
internal DefaultFrozenDictionary(Dictionary<TKey, TValue> source, IEqualityComparer<TKey> comparer)
: base(source, comparer)
internal DefaultFrozenDictionary(Dictionary<TKey, TValue> source, bool optimizeForReading)
: base(source, optimizeForReading)
{
}

Expand Down
Expand Up @@ -9,8 +9,8 @@ namespace System.Collections.Frozen
/// <typeparam name="T">The type of the values in the set.</typeparam>
internal sealed class DefaultFrozenSet<T> : ItemsFrozenSet<T, DefaultFrozenSet<T>.GSW>
{
internal DefaultFrozenSet(HashSet<T> source, IEqualityComparer<T> comparer)
: base(source, comparer)
internal DefaultFrozenSet(HashSet<T> source, bool optimizeForReading)
: base(source, optimizeForReading)
{
}

Expand Down
Expand Up @@ -11,7 +11,7 @@ namespace System.Collections.Frozen
internal sealed class EmptyFrozenDictionary<TKey, TValue> : FrozenDictionary<TKey, TValue>
where TKey : notnull
{
internal EmptyFrozenDictionary() : base(EqualityComparer<TKey>.Default) { }
internal EmptyFrozenDictionary(IEqualityComparer<TKey> comparer) : base(comparer) { }

/// <inheritdoc />
private protected override TKey[] KeysCore => Array.Empty<TKey>();
Expand Down
Expand Up @@ -2,15 +2,14 @@
// The .NET Foundation licenses this file to you under the MIT license.

using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;

namespace System.Collections.Frozen
{
/// <summary>Provides an empty <see cref="FrozenSet{T}"/> to use when there are zero values to be stored.</summary>
internal sealed class EmptyFrozenSet<T> : FrozenSet<T>
{
internal EmptyFrozenSet() : base(EqualityComparer<T>.Default) { }
internal EmptyFrozenSet(IEqualityComparer<T> comparer) : base(comparer) { }

/// <inheritdoc />
private protected override T[] ItemsCore => Array.Empty<T>();
Expand Down

0 comments on commit 53412f1

Please sign in to comment.