System.Collections.Immutable by Microsoft

<PackageReference Include="System.Collections.Immutable" Version="8.0.0-preview.4.23259.5" />

.NET API 252,080 bytes

 FrozenSet

public static class 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); } } }