FrozenSet
using System.Collections.Generic;
using System.Runtime.CompilerServices;
namespace System.Collections.Frozen
{
[System.Runtime.CompilerServices.NullableContext(1)]
[System.Runtime.CompilerServices.Nullable(0)]
public static class FrozenSet
{
public static FrozenSet<T> ToFrozenSet<[System.Runtime.CompilerServices.Nullable(2)] T>(this IEnumerable<T> source, [System.Runtime.CompilerServices.Nullable(new byte[] {
2,
1
})] IEqualityComparer<T> comparer = null)
{
GetUniqueValues(source, comparer, out FrozenSet<T> existing, out HashSet<T> uniqueValues);
return existing ?? ChooseImplementationOptimizedForConstruction(uniqueValues);
}
public static FrozenSet<T> ToFrozenSet<[System.Runtime.CompilerServices.Nullable(2)] T>(this IEnumerable<T> source, bool optimizeForReading)
{
return source.ToFrozenSet(null, optimizeForReading);
}
public static FrozenSet<T> ToFrozenSet<[System.Runtime.CompilerServices.Nullable(2)] T>(this IEnumerable<T> source, [System.Runtime.CompilerServices.Nullable(new byte[] {
2,
1
})] IEqualityComparer<T> comparer, bool optimizeForReading)
{
GetUniqueValues(source, comparer, out FrozenSet<T> existing, out HashSet<T> uniqueValues);
object frozenSet = existing;
if (frozenSet == null) {
if (!optimizeForReading)
return ChooseImplementationOptimizedForConstruction(uniqueValues);
frozenSet = ChooseImplementationOptimizedForReading(uniqueValues);
}
return (FrozenSet<T>)frozenSet;
}
private static void GetUniqueValues<T>(IEnumerable<T> source, IEqualityComparer<T> comparer, out FrozenSet<T> existing, out HashSet<T> uniqueValues)
{
ThrowHelper.ThrowIfNull(source, "source");
if (comparer == null)
comparer = EqualityComparer<T>.Default;
FrozenSet<T> frozenSet = source as FrozenSet<T>;
if (frozenSet != null && frozenSet.Comparer.Equals(comparer)) {
existing = frozenSet;
uniqueValues = null;
} else {
uniqueValues = (source as HashSet<T>);
if (uniqueValues == null || (uniqueValues.Count != 0 && !uniqueValues.Comparer.Equals(comparer)))
uniqueValues = new HashSet<T>(source, comparer);
if (uniqueValues.Count == 0) {
existing = ((comparer == FrozenSet<T>.Empty.Comparer) ? FrozenSet<T>.Empty : new EmptyFrozenSet<T>(comparer));
uniqueValues = null;
} else
existing = null;
}
}
private static FrozenSet<T> ChooseImplementationOptimizedForConstruction<T>(HashSet<T> source)
{
return new DefaultFrozenSet<T>(source, false);
}
private static FrozenSet<T> ChooseImplementationOptimizedForReading<T>(HashSet<T> source)
{
IEqualityComparer<T> comparer = source.Comparer;
if (typeof(T).IsValueType) {
if (comparer == EqualityComparer<T>.Default) {
if (source.Count <= 10) {
if (Constants.IsKnownComparable<T>())
return (FrozenSet<T>)new SmallValueTypeComparableFrozenSet<T>(source);
return (FrozenSet<T>)new SmallValueTypeDefaultComparerFrozenSet<T>(source);
}
if (typeof(T) == typeof(int))
return (FrozenSet<T>)new Int32FrozenSet((HashSet<int>)source);
return new ValueTypeDefaultComparerFrozenSet<T>(source);
}
} else if (typeof(T) == typeof(string) && !source.Contains(default(T)) && (comparer == EqualityComparer<T>.Default || comparer == StringComparer.Ordinal || comparer == StringComparer.OrdinalIgnoreCase)) {
HashSet<string> hashSet = (HashSet<string>)source;
string[] array = new string[hashSet.Count];
hashSet.CopyTo(array);
IEqualityComparer<string> equalityComparer = (IEqualityComparer<string>)comparer;
FrozenSet<string> frozenSet = LengthBucketsFrozenSet.CreateLengthBucketsFrozenSetIfAppropriate(array, equalityComparer);
if (frozenSet != null)
return (FrozenSet<T>)frozenSet;
KeyAnalyzer.Analyze(array, equalityComparer == StringComparer.OrdinalIgnoreCase, out KeyAnalyzer.AnalysisResults results);
frozenSet = (results.SubstringHashing ? (results.RightJustifiedSubstring ? ((!results.IgnoreCase) ? ((results.HashCount == 1) ? ((OrdinalStringFrozenSet)new OrdinalStringFrozenSet_RightJustifiedSingleChar(array, equalityComparer, results.MinimumLength, results.MaximumLengthDiff, results.HashIndex)) : ((OrdinalStringFrozenSet)new OrdinalStringFrozenSet_RightJustifiedSubstring(array, equalityComparer, results.MinimumLength, results.MaximumLengthDiff, results.HashIndex, results.HashCount))) : (results.AllAscii ? ((OrdinalStringFrozenSet)new OrdinalStringFrozenSet_RightJustifiedCaseInsensitiveAsciiSubstring(array, equalityComparer, results.MinimumLength, results.MaximumLengthDiff, results.HashIndex, results.HashCount)) : ((OrdinalStringFrozenSet)new OrdinalStringFrozenSet_RightJustifiedCaseInsensitiveSubstring(array, equalityComparer, results.MinimumLength, results.MaximumLengthDiff, results.HashIndex, results.HashCount)))) : ((!results.IgnoreCase) ? ((results.HashCount == 1) ? ((OrdinalStringFrozenSet)new OrdinalStringFrozenSet_LeftJustifiedSingleChar(array, equalityComparer, results.MinimumLength, results.MaximumLengthDiff, results.HashIndex)) : ((OrdinalStringFrozenSet)new OrdinalStringFrozenSet_LeftJustifiedSubstring(array, equalityComparer, results.MinimumLength, results.MaximumLengthDiff, results.HashIndex, results.HashCount))) : (results.AllAscii ? ((OrdinalStringFrozenSet)new OrdinalStringFrozenSet_LeftJustifiedCaseInsensitiveAsciiSubstring(array, equalityComparer, results.MinimumLength, results.MaximumLengthDiff, results.HashIndex, results.HashCount)) : ((OrdinalStringFrozenSet)new OrdinalStringFrozenSet_LeftJustifiedCaseInsensitiveSubstring(array, equalityComparer, results.MinimumLength, results.MaximumLengthDiff, results.HashIndex, results.HashCount))))) : ((!results.IgnoreCase) ? new OrdinalStringFrozenSet_Full(array, equalityComparer, results.MinimumLength, results.MaximumLengthDiff) : (results.AllAscii ? ((OrdinalStringFrozenSet)new OrdinalStringFrozenSet_FullCaseInsensitiveAscii(array, equalityComparer, results.MinimumLength, results.MaximumLengthDiff)) : ((OrdinalStringFrozenSet)new OrdinalStringFrozenSet_FullCaseInsensitive(array, equalityComparer, results.MinimumLength, results.MaximumLengthDiff)))));
return (FrozenSet<T>)frozenSet;
}
if (source.Count <= 4)
return new SmallFrozenSet<T>(source);
return new DefaultFrozenSet<T>(source, true);
}
}
}