Skip to content

Commit

Permalink
Fix ToFrozenDictionary(selectors) on empty sources
Browse files Browse the repository at this point in the history
As part of optimizing construction, the empty check when using ToFrozenDictionary taking selector delegates was skipped, leading to later failures when an empty source is used.
  • Loading branch information
stephentoub authored and github-actions committed Aug 15, 2023
1 parent c5aba1b commit 275be61
Show file tree
Hide file tree
Showing 3 changed files with 43 additions and 30 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ public static FrozenDictionary<TKey, TValue> ToFrozenDictionary<TKey, TValue>(th
public static FrozenDictionary<TKey, TSource> ToFrozenDictionary<TSource, TKey>(
this IEnumerable<TSource> source, Func<TSource, TKey> keySelector, IEqualityComparer<TKey>? comparer = null)
where TKey : notnull =>
CreateFromDictionary(source.ToDictionary(keySelector, comparer));
source.ToDictionary(keySelector, comparer).ToFrozenDictionary(comparer);

/// <summary>Creates a <see cref="FrozenDictionary{TKey, TElement}"/> from an <see cref="IEnumerable{TSource}"/> according to specified key selector and element selector functions.</summary>
/// <typeparam name="TSource">The type of the elements of <paramref name="source"/>.</typeparam>
Expand All @@ -55,7 +55,7 @@ public static FrozenDictionary<TKey, TSource> ToFrozenDictionary<TSource, TKey>(
public static FrozenDictionary<TKey, TElement> ToFrozenDictionary<TSource, TKey, TElement>(
this IEnumerable<TSource> source, Func<TSource, TKey> keySelector, Func<TSource, TElement> elementSelector, IEqualityComparer<TKey>? comparer = null)
where TKey : notnull =>
CreateFromDictionary(source.ToDictionary(keySelector, elementSelector, comparer));
source.ToDictionary(keySelector, elementSelector, comparer).ToFrozenDictionary(comparer);

/// <summary>
/// Extracts from the source either an existing <see cref="FrozenDictionary{TKey,TValue}"/> instance or a <see cref="Dictionary{TKey,TValue}"/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -86,23 +86,35 @@ public void NullSource_ThrowsException()
[Fact]
public void EmptySource_ProducedFrozenDictionaryEmpty()
{
Assert.Same(FrozenDictionary<TKey, TValue>.Empty, new Dictionary<TKey, TValue>().ToFrozenDictionary());
Assert.Same(FrozenDictionary<TKey, TValue>.Empty, Enumerable.Empty<KeyValuePair<TKey, TValue>>().ToFrozenDictionary());
Assert.Same(FrozenDictionary<TKey, TValue>.Empty, Array.Empty<KeyValuePair<TKey, TValue>>().ToFrozenDictionary());
Assert.Same(FrozenDictionary<TKey, TValue>.Empty, new List<KeyValuePair<TKey, TValue>>().ToFrozenDictionary());
IEnumerable<KeyValuePair<TKey, TValue>>[] sources = new[]
{
new Dictionary<TKey, TValue>(),
Enumerable.Empty<KeyValuePair<TKey, TValue>>(),
Array.Empty<KeyValuePair<TKey, TValue>>(),
new List<KeyValuePair<TKey, TValue>>()
};

foreach (IEqualityComparer<TKey> comparer in new IEqualityComparer<TKey>[] { null, EqualityComparer<TKey>.Default })
foreach (IEnumerable<KeyValuePair<TKey, TValue>> source in sources)
{
Assert.Same(FrozenDictionary<TKey, TValue>.Empty, new Dictionary<TKey, TValue>().ToFrozenDictionary(comparer));
Assert.Same(FrozenDictionary<TKey, TValue>.Empty, Enumerable.Empty<KeyValuePair<TKey, TValue>>().ToFrozenDictionary(comparer));
Assert.Same(FrozenDictionary<TKey, TValue>.Empty, Array.Empty<KeyValuePair<TKey, TValue>>().ToFrozenDictionary(comparer));
Assert.Same(FrozenDictionary<TKey, TValue>.Empty, new List<KeyValuePair<TKey, TValue>>().ToFrozenDictionary(comparer));
}
Assert.Same(FrozenDictionary<TKey, TValue>.Empty, source.ToFrozenDictionary());
Assert.Same(FrozenDictionary<TKey, KeyValuePair<TKey, TValue>>.Empty, source.ToFrozenDictionary(s => s.Key));
Assert.Same(FrozenDictionary<TKey, TValue>.Empty, source.ToFrozenDictionary(s => s.Key, s => s.Value));

Assert.NotSame(FrozenDictionary<TKey, TValue>.Empty, new Dictionary<TKey, TValue>().ToFrozenDictionary(NonDefaultEqualityComparer<TKey>.Instance));
Assert.NotSame(FrozenDictionary<TKey, TValue>.Empty, Enumerable.Empty<KeyValuePair<TKey, TValue>>().ToFrozenDictionary(NonDefaultEqualityComparer<TKey>.Instance));
Assert.NotSame(FrozenDictionary<TKey, TValue>.Empty, Array.Empty<KeyValuePair<TKey, TValue>>().ToFrozenDictionary(NonDefaultEqualityComparer<TKey>.Instance));
Assert.NotSame(FrozenDictionary<TKey, TValue>.Empty, new List<KeyValuePair<TKey, TValue>>().ToFrozenDictionary(NonDefaultEqualityComparer<TKey>.Instance));
foreach (IEqualityComparer<TKey> comparer in new IEqualityComparer<TKey>[] { null, EqualityComparer<TKey>.Default })
{
Assert.Same(FrozenDictionary<TKey, TValue>.Empty, source.ToFrozenDictionary(comparer));
Assert.Same(FrozenDictionary<TKey, KeyValuePair<TKey, TValue>>.Empty, source.ToFrozenDictionary(s => s.Key, comparer));
Assert.Same(FrozenDictionary<TKey, TValue>.Empty, source.ToFrozenDictionary(s => s.Key, s => s.Value, comparer));
}

Assert.NotSame(FrozenDictionary<TKey, TValue>.Empty, source.ToFrozenDictionary(NonDefaultEqualityComparer<TKey>.Instance));
Assert.NotSame(FrozenDictionary<TKey, KeyValuePair<TKey, TValue>>.Empty, source.ToFrozenDictionary(s => s.Key, NonDefaultEqualityComparer<TKey>.Instance));
Assert.NotSame(FrozenDictionary<TKey, TValue>.Empty, source.ToFrozenDictionary(s => s.Key, s => s.Value, NonDefaultEqualityComparer<TKey>.Instance));

Assert.Equal(0, source.ToFrozenDictionary(NonDefaultEqualityComparer<TKey>.Instance).Count);
Assert.Equal(0, source.ToFrozenDictionary(s => s.Key, NonDefaultEqualityComparer<TKey>.Instance).Count);
Assert.Equal(0, source.ToFrozenDictionary(s => s.Key, s => s.Value, NonDefaultEqualityComparer<TKey>.Instance).Count);
}
}

[Fact]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,23 +63,24 @@ public void NullSource_ThrowsException()
[Fact]
public void EmptySource_ProducedFrozenSetEmpty()
{
Assert.Same(FrozenSet<T>.Empty, new List<T>().ToFrozenSet());
Assert.Same(FrozenSet<T>.Empty, Enumerable.Empty<T>().ToFrozenSet());
Assert.Same(FrozenSet<T>.Empty, Array.Empty<T>().ToFrozenSet());
Assert.Same(FrozenSet<T>.Empty, new List<T>().ToFrozenSet());
IEnumerable<T>[] sources = new[]
{
new List<T>(),
Enumerable.Empty<T>(),
Array.Empty<T>(),
};

foreach (IEqualityComparer<T> comparer in new IEqualityComparer<T>[] { null, EqualityComparer<T>.Default })
foreach (IEnumerable<T> source in sources)
{
Assert.Same(FrozenSet<T>.Empty, new List<T>().ToFrozenSet(comparer));
Assert.Same(FrozenSet<T>.Empty, Enumerable.Empty<T>().ToFrozenSet(comparer));
Assert.Same(FrozenSet<T>.Empty, Array.Empty<T>().ToFrozenSet(comparer));
Assert.Same(FrozenSet<T>.Empty, new List<T>().ToFrozenSet(comparer));
}
Assert.Same(FrozenSet<T>.Empty, source.ToFrozenSet());

foreach (IEqualityComparer<T> comparer in new IEqualityComparer<T>[] { null, EqualityComparer<T>.Default })
{
Assert.Same(FrozenSet<T>.Empty, source.ToFrozenSet(comparer));
}

Assert.NotSame(FrozenSet<T>.Empty, new List<T>().ToFrozenSet(NonDefaultEqualityComparer<T>.Instance));
Assert.NotSame(FrozenSet<T>.Empty, Enumerable.Empty<T>().ToFrozenSet(NonDefaultEqualityComparer<T>.Instance));
Assert.NotSame(FrozenSet<T>.Empty, Array.Empty<T>().ToFrozenSet(NonDefaultEqualityComparer<T>.Instance));
Assert.NotSame(FrozenSet<T>.Empty, new List<T>().ToFrozenSet(NonDefaultEqualityComparer<T>.Instance));
Assert.NotSame(FrozenSet<T>.Empty, source.ToFrozenSet(NonDefaultEqualityComparer<T>.Instance));
}
}

[Fact]
Expand Down

0 comments on commit 275be61

Please sign in to comment.