< Summary

Information
Class: SwiftCollections.SwiftDictionary<T1, T2>
Assembly: SwiftCollections
File(s): /home/runner/work/SwiftCollections/SwiftCollections/src/SwiftCollections/Collection/SwiftDictionary.cs
Line coverage
95%
Covered lines: 463
Uncovered lines: 21
Coverable lines: 484
Total lines: 1414
Line coverage: 95.6%
Branch coverage
94%
Covered branches: 194
Total branches: 206
Branch coverage: 94.1%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
.ctor()100%11100%
.ctor(...)100%11100%
.ctor(...)100%22100%
.ctor(...)75%44100%
.ctor(...)100%11100%
get_Count()100%11100%
get_Capacity()100%11100%
get_Comparer()100%11100%
get_Item(...)100%11100%
set_Item(...)100%22100%
System.Collections.IDictionary.get_Item(...)100%44100%
System.Collections.IDictionary.set_Item(...)100%1170%
get_Keys()100%22100%
System.Collections.IDictionary.get_Keys()100%22100%
get_Values()100%22100%
System.Collections.IDictionary.get_Values()100%22100%
System.Collections.Generic.ICollection<System.Collections.Generic.KeyValuePair<TKey,TValue>>.get_IsReadOnly()100%11100%
System.Collections.IDictionary.get_IsReadOnly()100%11100%
System.Collections.IDictionary.get_IsFixedSize()100%11100%
System.Collections.ICollection.get_IsSynchronized()100%11100%
get_SyncRoot()100%22100%
get_State()100%22100%
set_State(...)100%44100%
Add(...)100%11100%
Add(...)100%11100%
System.Collections.Generic.IDictionary<TKey,TValue>.Add(...)100%11100%
Add(...)100%1170%
InsertIfNotExist(...)95.83%242493.75%
Remove(...)100%1616100%
System.Collections.IDictionary.Remove(...)100%22100%
Remove(...)100%44100%
Clear()100%44100%
CheckLoadThreshold()100%22100%
EnsureCapacity(...)100%22100%
Resize(...)100%88100%
TrimExcess()91.66%1212100%
CalculateAdaptiveResizeFactors(...)100%66100%
Initialize(...)100%22100%
ContainsKey(...)100%11100%
System.Collections.IDictionary.Contains(...)100%22100%
Contains(...)100%44100%
TryGetValue(...)100%22100%
CopyTo(...)100%44100%
CopyTo(...)75%4490.9%
CopyToDictionaryEntries(...)100%44100%
CopyToObjects(...)100%2271.42%
CopyToObjects(...)100%44100%
SetComparer(...)50%2285.71%
SwitchToRandomizedComparer()50%2285.71%
RehashEntries()100%88100%
FindEntry(...)92.85%1414100%
GetEnumerator()100%11100%
System.Collections.Generic.IEnumerable<System.Collections.Generic.KeyValuePair<TKey,TValue>>.GetEnumerator()100%11100%
System.Collections.IEnumerable.GetEnumerator()100%11100%
System.Collections.IDictionary.GetEnumerator()100%11100%
.ctor(...)100%11100%
System.Collections.IDictionaryEnumerator.get_Key()100%11100%
System.Collections.IDictionaryEnumerator.get_Value()100%11100%
System.Collections.IDictionaryEnumerator.get_Entry()100%11100%
get_Current()100%11100%
System.Collections.IEnumerator.get_Current()100%22100%
MoveNext()100%44100%
Reset()100%11100%
Dispose()100%11100%
.ctor(...)100%11100%
get_Count()100%11100%
System.Collections.ICollection.get_IsSynchronized()100%11100%
System.Collections.ICollection.get_SyncRoot()100%11100%
System.Collections.Generic.ICollection<TKey>.get_IsReadOnly()100%11100%
System.Collections.Generic.ICollection<TKey>.Add(...)100%11100%
System.Collections.Generic.ICollection<TKey>.Clear()100%11100%
System.Collections.Generic.ICollection<TKey>.Contains(...)100%11100%
System.Collections.Generic.ICollection<TKey>.Remove(...)100%11100%
CopyTo(...)100%44100%
System.Collections.ICollection.CopyTo(...)75%8887.5%
GetEnumerator()100%11100%
System.Collections.Generic.IEnumerable<TKey>.GetEnumerator()100%11100%
System.Collections.IEnumerable.GetEnumerator()100%11100%
.ctor(...)100%11100%
get_Current()100%11100%
System.Collections.IEnumerator.get_Current()100%11100%
MoveNext()100%44100%
Reset()100%11100%
Dispose()100%11100%
.ctor(...)100%11100%
get_Count()100%11100%
System.Collections.Generic.ICollection<TValue>.get_IsReadOnly()100%11100%
System.Collections.ICollection.get_IsSynchronized()100%11100%
System.Collections.ICollection.get_SyncRoot()100%11100%
System.Collections.Generic.ICollection<TValue>.Add(...)100%11100%
System.Collections.Generic.ICollection<TValue>.Clear()100%11100%
System.Collections.Generic.ICollection<TValue>.Contains(...)83.33%7675%
System.Collections.Generic.ICollection<TValue>.Remove(...)100%11100%
CopyTo(...)100%44100%
System.Collections.ICollection.CopyTo(...)87.5%8881.25%
GetEnumerator()100%11100%
System.Collections.Generic.IEnumerable<TValue>.GetEnumerator()100%11100%
System.Collections.IEnumerable.GetEnumerator()100%11100%
.ctor(...)100%11100%
get_Current()100%11100%
System.Collections.IEnumerator.get_Current()100%11100%
MoveNext()75%4471.42%
Reset()100%11100%
Dispose()100%11100%

File(s)

/home/runner/work/SwiftCollections/SwiftCollections/src/SwiftCollections/Collection/SwiftDictionary.cs

#LineLine coverage
 1using Chronicler;
 2using MemoryPack;
 3using System;
 4using System.Collections;
 5using System.Collections.Generic;
 6using System.Runtime.CompilerServices;
 7using System.Text.Json.Serialization;
 8
 9namespace SwiftCollections;
 10
 11/// <summary>Specifies that the method or property will ensure that the listed field and property members have not-null 
 12[AttributeUsage(AttributeTargets.Method | AttributeTargets.Property, Inherited = false, AllowMultiple = true)]
 13#if SYSTEM_PRIVATE_CORELIB
 14    public
 15#else
 16internal
 17#endif
 18    sealed class MemberNotNullAttribute : Attribute
 19{
 20    /// <summary>Initializes the attribute with a field or property member.</summary>
 21    /// <param name="member">
 22    /// The field or property member that is promised to be not-null.
 23    /// </param>
 24    public MemberNotNullAttribute(string member) => Members = new[] { member };
 25
 26    /// <summary>Initializes the attribute with the list of field and property members.</summary>
 27    /// <param name="members">
 28    /// The list of field and property members that are promised to be not-null.
 29    /// </param>
 30    public MemberNotNullAttribute(params string[] members) => Members = members;
 31
 32    /// <summary>Gets field or property member names.</summary>
 33    public string[] Members { get; }
 34}
 35
 36/// <summary>
 37/// A high-performance, memory-efficient dictionary providing lightning-fast O(1) operations for addition, retrieval, an
 38/// </summary>
 39/// <typeparam name="TKey">Specifies the type of keys in the dictionary.</typeparam>
 40/// <typeparam name="TValue">Specifies the type of values in the dictionary.</typeparam>
 41/// <remarks>
 42/// The comparer is not serialized. After deserialization the dictionary reverts
 43/// to the same default comparer selection used by a new instance. String keys
 44/// use SwiftCollections' deterministic default comparer. Object keys use a
 45/// SwiftCollections comparer that hashes strings deterministically, while other
 46/// object-key determinism still depends on the underlying key type's
 47/// <see cref="object.GetHashCode()"/> implementation. Other key types use
 48/// <see cref="EqualityComparer{TKey}.Default"/>.
 49///
 50/// If a custom comparer is required it can be reapplied using
 51/// <see cref="SetComparer(IEqualityComparer{TKey})"/>.
 52/// </remarks>
 53[Serializable]
 54[JsonConverter(typeof(StateJsonConverterFactory))]
 55[MemoryPackable]
 56public partial class SwiftDictionary<TKey, TValue> : IStateBacked<SwiftDictionaryState<TKey, TValue>>, IDictionary<TKey,
 57    where TKey : notnull
 58{
 59    #region Constants
 60
 61    /// <summary>
 62    /// The default initial capacity of the dictionary.
 63    /// </summary>
 64    public const int DefaultCapacity = 8;
 65
 66    /// <summary>
 67    /// Determines the maximum allowable load factor before resizing the hash set to maintain performance.
 68    /// </summary>
 69    private const double _LoadFactorThreshold = 0.82;
 70
 71    #endregion
 72
 73    #region Fields
 74
 75    /// <summary>
 76    /// The array containing the entries of the dictionary.
 77    /// </summary>
 78    protected Entry[] _entries;
 79
 80    /// <summary>
 81    /// The total number of entries in the dictionary
 82    /// </summary>
 83    private int _count;
 84
 85    /// <summary>
 86    /// The index of the last used entry in the dictionary.
 87    /// </summary>
 88    private int _lastIndex;
 89
 90    /// <summary>
 91    /// A mask used for efficiently computing the entry arrayIndex from a hash code.
 92    /// This is typically the size of the entry array minus one, assuming the size is a power of two.
 93    /// </summary>
 94    private int _entryMask;
 95
 96    /// <summary>
 97    /// The comparer used to determine equality of keys and to generate hash codes.
 98    /// </summary>
 99    protected IEqualityComparer<TKey> _comparer;
 100
 101    /// <summary>
 102    /// Specifies the dynamic growth factor for resizing, adjusted based on recent usage patterns.
 103    /// </summary>
 104    private int _adaptiveResizeFactor;
 105
 106    /// <summary>
 107    /// Tracks the count threshold at which the hash set should resize based on the load factor.
 108    /// </summary>
 109    private uint _nextResizeCount;
 110
 111    /// <summary>
 112    /// Represents the moving average of the fill rate, used to dynamically adjust resizing behavior.
 113    /// </summary>
 114    private double _movingFillRate;
 115
 116    /// <summary>
 117    /// The maximum number of steps allowed during probing to resolve collisions.
 118    /// </summary>
 119    private int _maxStepCount;
 120
 121    /// <summary>
 122    /// A version counter used to track modifications to the dictionary.
 123    /// Incremented on mutations to detect changes during enumeration and ensure enumerator validity.
 124    /// </summary>
 125    [NonSerialized]
 126    protected uint _version;
 127
 128    /// <summary>
 129    /// An object that can be used to synchronize access to the SwiftDictionary.
 130    /// </summary>
 131    [NonSerialized]
 132    private object? _syncRoot;
 133
 134    #endregion
 135
 136    #region Nested Types
 137
 138    /// <summary>
 139    /// Represents a single key-value pair in the dictionary, including its hash code for quick access.
 140    /// </summary>
 141    protected struct Entry
 142    {
 143        /// <summary>
 144        /// Gets or sets the key associated with this instance.
 145        /// </summary>
 146        public TKey Key;
 147
 148        /// <summary>
 149        /// Gets or sets the value associated with this instance.
 150        /// </summary>
 151        public TValue Value;
 152
 153        /// <summary>
 154        /// Gets or sets the lower 31 bits of the hash code associated with this entry.
 155        /// </summary>
 156        /// <remarks>
 157        /// A value of -1 indicates that the entry is a deleted probe tombstone.
 158        /// Only the lower 31 bits are used; the highest bit is reserved.</remarks>
 159        public int HashCode;
 160
 161        /// <summary>
 162        /// Indicates whether the item is currently in use.
 163        /// </summary>
 164        public bool IsUsed;
 165    }
 166
 167    #endregion
 168
 169    #region Constructors
 170
 171    /// <summary>
 172    /// Initialize a new instance of <see cref="SwiftDictionary{TKey, TValue}"/> with customizable capacity and comparer
 173    /// </summary>
 174174    public SwiftDictionary() : this(DefaultCapacity, null) { }
 175
 176    /// <inheritdoc cref="SwiftDictionary()"/>
 230177    public SwiftDictionary(int capacity, IEqualityComparer<TKey>? comparer = null)
 178    {
 230179        Initialize(capacity, comparer);
 180
 230181        SwiftThrowHelper.ThrowIfNull(_entries, nameof(_entries));
 230182        SwiftThrowHelper.ThrowIfNull(_comparer, nameof(_comparer));
 230183    }
 184
 185    /// <inheritdoc cref="SwiftDictionary()"/>
 2186    public SwiftDictionary(IDictionary<TKey, TValue> dictionary, IEqualityComparer<TKey>? comparer = null)
 187    {
 2188        SwiftThrowHelper.ThrowIfNull(dictionary, nameof(dictionary));
 189
 1190        Initialize(dictionary.Count, comparer);
 191
 1192        SwiftThrowHelper.ThrowIfNull(_entries, nameof(_entries));
 1193        SwiftThrowHelper.ThrowIfNull(_comparer, nameof(_comparer));
 194
 6195        foreach (KeyValuePair<TKey, TValue> kvp in dictionary)
 2196            InsertIfNotExist(kvp.Key, kvp.Value);
 1197    }
 198
 199    /// <inheritdoc cref="SwiftDictionary()"/>
 2200    public SwiftDictionary(IEnumerable<KeyValuePair<TKey, TValue>> collection, IEqualityComparer<TKey>? comparer = null)
 201    {
 2202        SwiftThrowHelper.ThrowIfNull(collection, nameof(collection));
 203
 1204        int count = (collection as ICollection<TKey>)?.Count ?? DefaultCapacity;
 205        // Dynamic padding based on collision estimation
 1206        int size = (int)(count / _LoadFactorThreshold);
 1207        Initialize(size, comparer);
 208
 1209        SwiftThrowHelper.ThrowIfNull(_entries, nameof(_entries));
 1210        SwiftThrowHelper.ThrowIfNull(_comparer, nameof(_comparer));
 211
 6212        foreach (KeyValuePair<TKey, TValue> kvp in collection)
 2213            InsertIfNotExist(kvp.Key, kvp.Value);
 1214    }
 215
 216    ///  <summary>
 217    ///  Initializes a new instance of the <see cref="SwiftDictionary{TKey, TValue}"/> class with the specified <see cre
 218    ///  </summary>
 219    ///  <param name="state">The state containing the internal array, count, offset, and version for initialization.</pa
 220    [MemoryPackConstructor]
 11221    public SwiftDictionary(SwiftDictionaryState<TKey, TValue> state)
 222    {
 11223        State = state;
 224
 11225        SwiftThrowHelper.ThrowIfNull(_entries, nameof(_entries));
 11226        SwiftThrowHelper.ThrowIfNull(_comparer, nameof(_comparer));
 11227    }
 228
 229    #endregion
 230
 231    #region Properties
 232
 233    /// <summary>
 234    /// Gets the number of elements contained in the dictionary.
 235    /// </summary>
 236    [JsonIgnore]
 237    [MemoryPackIgnore]
 23238    public int Count => _count;
 239
 240    /// <summary>
 241    /// Gets the total number of elements that the collection can hold without resizing.
 242    /// </summary>
 243    [JsonIgnore]
 244    [MemoryPackIgnore]
 7245    public int Capacity => _entries.Length;
 246
 247    /// <summary>
 248    /// Gets the equality comparer used to determine equality of keys in the collection.
 249    /// </summary>
 250    [JsonIgnore]
 251    [MemoryPackIgnore]
 11252    public IEqualityComparer<TKey> Comparer => _comparer;
 253
 254    /// <summary>
 255    /// Gets or sets the value associated with the specified key.
 256    /// </summary>
 257    /// <remarks>
 258    /// Getting a value with a key that does not exist will throw an exception.
 259    /// Setting a value for a key that does not exist will add a new entry with the specified key and value.
 260    /// </remarks>
 261    /// <param name="key">The key whose value to get or set.</param>
 262    [JsonIgnore]
 263    [MemoryPackIgnore]
 264    public TValue this[TKey key]
 265    {
 266        get
 267        {
 4166268            int index = FindEntry(key);
 4166269            SwiftThrowHelper.ThrowIfKeyInvalid(index, key);
 4164270            return _entries[index].Value;
 271        }
 272        set
 273        {
 9831274            int index = FindEntry(key);
 9831275            if (index >= 0)
 6512276                _entries[index].Value = value;
 277            else
 278            {
 3319279                CheckLoadThreshold();
 3319280                InsertIfNotExist(key, value);
 281            }
 3319282        }
 283    }
 284
 285    /// <inheritdoc/>
 286    [JsonIgnore]
 287    [MemoryPackIgnore]
 288    object? IDictionary.this[object obj]
 289    {
 290        get
 291        {
 17292            SwiftThrowHelper.ThrowIfNull(obj, nameof(obj));
 293
 16294            if (obj is TKey key)
 295            {
 15296                int index = FindEntry(key);
 29297                if (index >= 0) return _entries[index].Value;
 298            }
 2299            return null;
 300        }
 301        set
 302        {
 2303            SwiftThrowHelper.ThrowIfNullAndNullsAreIllegal(value, default(TValue));
 304            try
 305            {
 2306                TKey tempKey = (TKey)obj;
 307                try
 308                {
 1309                    this[tempKey] = (TValue)value!;
 0310                }
 1311                catch (InvalidCastException)
 312                {
 1313                    throw new ArgumentException($"Value {value} does not match expected {typeof(TValue)}");
 314                }
 0315            }
 1316            catch (InvalidCastException)
 317            {
 1318                throw new ArgumentException($"Key {obj} does not match expected {typeof(TKey)}");
 319            }
 0320        }
 321    }
 322
 323    /// <summary>
 324    /// The collection containing the keys of the dictionary.
 325    /// </summary>
 326    [JsonIgnore]
 327    [MemoryPackIgnore]
 328    private KeyCollection? _keyCollection;
 329
 330    /// <inheritdoc/>
 331    [JsonIgnore]
 332    [MemoryPackIgnore]
 10333    public ICollection<TKey> Keys => _keyCollection ??= new KeyCollection(this);
 334
 335    [JsonIgnore]
 336    [MemoryPackIgnore]
 4337    ICollection IDictionary.Keys => _keyCollection ??= new KeyCollection(this);
 338
 339    /// <summary>
 340    /// The collection containing the values of the dictionary.
 341    /// </summary>
 342    [JsonIgnore]
 343    [MemoryPackIgnore]
 344    private ValueCollection? _valueCollection;
 345
 346    /// <inheritdoc/>
 347    [JsonIgnore]
 348    [MemoryPackIgnore]
 10349    public ICollection<TValue> Values => _valueCollection ??= new ValueCollection(this);
 350
 351    [JsonIgnore]
 352    [MemoryPackIgnore]
 1353    ICollection IDictionary.Values => _valueCollection ??= new ValueCollection(this);
 354
 355    [JsonIgnore]
 356    [MemoryPackIgnore]
 1357    bool ICollection<KeyValuePair<TKey, TValue>>.IsReadOnly => false;
 358
 359    [JsonIgnore]
 1360    [MemoryPackIgnore] bool IDictionary.IsReadOnly => false;
 1361    bool IDictionary.IsFixedSize => false;
 362
 363    [JsonIgnore]
 364    [MemoryPackIgnore]
 1365    bool ICollection.IsSynchronized => false;
 366
 367    /// <inheritdoc/>
 368    [JsonIgnore]
 369    [MemoryPackIgnore]
 3370    public object SyncRoot => _syncRoot ??= new object();
 371
 372    /// <summary>
 373    /// Gets or sets the current state of the dictionary, including all key-value pairs.
 374    /// </summary>
 375    /// <remarks>
 376    /// The state can be used to serialize or restore the contents of the dictionary.
 377    /// Setting this property replaces the entire contents of the dictionary with the provided state.
 378    /// The setter is intended for internal use and is not accessible to external callers.
 379    /// </remarks>
 380    [JsonInclude]
 381    [MemoryPackInclude]
 382    public SwiftDictionaryState<TKey, TValue> State
 383    {
 384        get
 385        {
 15386            if (_count == 0)
 2387                return new SwiftDictionaryState<TKey, TValue>(Array.Empty<KeyValuePair<TKey, TValue>>());
 388
 13389            var items = new KeyValuePair<TKey, TValue>[_count];
 13390            CopyTo(items, 0);
 391
 13392            return new SwiftDictionaryState<TKey, TValue>(items);
 393        }
 394        internal set
 395        {
 16396            SwiftThrowHelper.ThrowIfNull(value.Items, nameof(value.Items));
 397
 16398            var items = value.Items;
 16399            int count = items.Length;
 400
 16401            if (count == 0)
 402            {
 3403                Initialize(DefaultCapacity);
 3404                _count = 0;
 3405                _version = 0;
 3406                return;
 407            }
 408
 13409            int size = (int)(count / _LoadFactorThreshold);
 13410            Initialize(size);
 411
 102412            foreach (var kvp in items)
 38413                InsertIfNotExist(kvp.Key, kvp.Value);
 414
 13415            _version = 0;
 13416        }
 417    }
 418
 419    #endregion
 420
 421    #region Collection Manipulation
 422
 423    /// <summary>
 424    /// Attempts to add the specified key and value to the dictionary.
 425    /// </summary>
 426    /// <param name="key">The key of the element to add.</param>
 427    /// <param name="value">The value of the element to add.</param>
 428    /// <returns>
 429    /// true if the key/value pair was added to the dictionary successfully;
 430    /// false if the key already exists.
 431    /// </returns>
 432    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 433    public virtual bool Add(TKey key, TValue value)
 434    {
 117494435        CheckLoadThreshold();
 117494436        return InsertIfNotExist(key, value);
 437    }
 438
 439    /// <inheritdoc/>
 1440    public void Add(KeyValuePair<TKey, TValue> item) => Add(item.Key, item.Value);
 441
 1442    void IDictionary<TKey, TValue>.Add(TKey key, TValue value) => Add(key, value);
 443
 444    /// <inheritdoc/>
 445    public void Add(object key, object? value)
 446    {
 3447        SwiftThrowHelper.ThrowIfNullAndNullsAreIllegal(value, default(TValue));
 448
 449        try
 450        {
 3451            TKey tempKey = (TKey)key;
 452            try
 453            {
 2454                Add(tempKey, (TValue)value!);
 0455            }
 1456            catch (InvalidCastException)
 457            {
 1458                throw new ArgumentException($"Value {value} does not match expected {typeof(TValue)}");
 459            }
 0460        }
 1461        catch (InvalidCastException)
 462        {
 1463            throw new ArgumentException($"Key {key} does not match expected {typeof(TKey)}");
 464        }
 0465    }
 466
 467    /// <summary>
 468    /// Inserts a key/value pair into the dictionary. If the key already exists and
 469    /// pair is added, or the method returns false if the key already exists.
 470    /// </summary>
 471    /// <param name="key">The key to insert or update.</param>
 472    /// <param name="value">The value to insert or update.</param>
 473    /// <returns>
 474    /// true if the key/value pair was added to the dictionary successfully;
 475    /// false if the key already exists.
 476    /// </returns>
 477    /// <exception cref="ArgumentNullException">Thrown when the key is null.</exception>
 478    internal virtual bool InsertIfNotExist(TKey key, TValue value)
 479    {
 120856480        SwiftThrowHelper.ThrowIfNullGeneric(key, nameof(key));
 481
 120854482        int hashCode = _comparer.GetHashCode(key) & 0x7FFFFFFF;
 120854483        int entryIndex = hashCode & _entryMask;
 484
 120854485        int firstDeletedIndex = -1;
 120854486        int step = 1;
 120854487        int probeLimit = _entries.Length;
 269073488        while ((uint)step <= (uint)probeLimit)
 489        {
 269073490            ref Entry entry = ref _entries[entryIndex];
 269073491            if (entry.IsUsed)
 492            {
 148251493                if (entry.HashCode == hashCode && _comparer.Equals(entry.Key, key))
 43494                    return false; // Item already exists
 495            }
 120822496            else if (entry.HashCode == -1)
 497            {
 20498                if (firstDeletedIndex < 0) firstDeletedIndex = entryIndex;
 499            }
 500            else
 501            {
 502                break;
 503            }
 504
 148219505            entryIndex = (entryIndex + step * step) & _entryMask; // Quadratic probing
 148219506            step++;
 507        }
 508
 120811509        if (firstDeletedIndex >= 0)
 8510            entryIndex = firstDeletedIndex;
 120803511        else if ((uint)step > (uint)probeLimit)
 512        {
 0513            Resize(_entries.Length * _adaptiveResizeFactor);
 0514            return InsertIfNotExist(key, value);
 515        }
 516
 137340517        if ((uint)entryIndex > (uint)_lastIndex) _lastIndex = entryIndex;
 518
 120811519        _entries[entryIndex].HashCode = hashCode;
 120811520        _entries[entryIndex].Key = key;
 120811521        _entries[entryIndex].Value = value;
 120811522        _entries[entryIndex].IsUsed = true;
 120811523        _count++;
 120811524        _version++;
 525
 120811526        if ((uint)step > (uint)_maxStepCount)
 527        {
 1416528            _maxStepCount = step;
 1416529            if (_comparer is not IRandomedEqualityComparer && _maxStepCount > 100)
 1530                SwitchToRandomizedComparer();  // Attempt to recompute hash code with potential randomization for better
 531        }
 532
 533
 120811534        return true;
 535    }
 536
 537    /// <inheritdoc/>
 538    public virtual bool Remove(TKey key)
 539    {
 6080540        if (key == null) return false;
 541
 6078542        int hashCode = _comparer.GetHashCode(key) & 0x7FFFFFFF;
 6078543        int entryIndex = hashCode & _entryMask;
 544
 6078545        int step = 0;
 6538546        while ((uint)step <= (uint)_lastIndex)
 547        {
 6537548            ref Entry entry = ref _entries[entryIndex];
 549            // Stop probing if an unused entry is found (not deleted)
 6537550            if (!entry.IsUsed && entry.HashCode != -1)
 1551                return false;
 6536552            if (entry.IsUsed && entry.HashCode == hashCode && _comparer.Equals(entry.Key, key))
 553            {
 554                // Mark entry as deleted
 6076555                entry.IsUsed = false;
 6076556                entry.Key = default!;
 6076557                entry.Value = default!;
 6076558                entry.HashCode = -1;
 6076559                _count--;
 6087560                if ((uint)_count == 0) _lastIndex = 0;
 6076561                _version++;
 6076562                return true;
 563            }
 564
 565            // Move to the next entry using linear probing
 460566            step++;
 460567            entryIndex = (entryIndex + step * step) & _entryMask;
 568        }
 1569        return false; // Item not found after full loop
 570    }
 571
 572    void IDictionary.Remove(object obj)
 573    {
 1574        SwiftThrowHelper.ThrowIfNull(obj, nameof(obj));
 2575        if (obj is TKey key) Remove(key);
 1576    }
 577
 578    /// <inheritdoc/>
 579    public bool Remove(KeyValuePair<TKey, TValue> item)
 580    {
 2581        int index = FindEntry(item.Key);
 2582        if (index >= 0 && EqualityComparer<TValue>.Default.Equals(_entries[index].Value, item.Value))
 583        {
 1584            Remove(item.Key);
 1585            return true;
 586        }
 1587        return false;
 588    }
 589
 590    /// <inheritdoc/>
 591    public virtual void Clear()
 592    {
 1062593        if ((uint)_count == 0) return;
 594
 6604595        for (uint i = 0; i <= (uint)_lastIndex; i++)
 596        {
 597            // Clear is a full reset, not a delete; future probes must be able to stop
 598            // at these now-empty slots instead of treating them as tombstones.
 2244599            _entries[i].HashCode = 0;
 2244600            _entries[i].Key = default!;
 2244601            _entries[i].Value = default!;
 2244602            _entries[i].IsUsed = false;
 603        }
 604
 1058605        _count = 0;
 1058606        _lastIndex = 0;
 1058607        _maxStepCount = 0;
 1058608        _movingFillRate = 0;
 1058609        _adaptiveResizeFactor = 4;
 610
 1058611        _version++;
 1058612    }
 613
 614    #endregion
 615
 616    #region Capacity Management
 617
 618    /// <summary>
 619    /// Ensures that the dictionary is resized when the current load factor exceeds the predefined threshold.
 620    /// </summary>
 621    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 622    protected void CheckLoadThreshold()
 623    {
 120814624        if ((uint)_count >= _nextResizeCount)
 61625            Resize(_entries.Length * _adaptiveResizeFactor);
 120814626    }
 627
 628    /// <summary>
 629    /// Ensures that the dictionary can hold up to the specified number of entries, if not it resizes.
 630    /// </summary>
 631    /// <param name="capacity">The minimum capacity to ensure.</param>
 632    /// <returns>The new capacity of the dictionary.</returns>
 633    /// <exception cref="ArgumentOutOfRangeException">The capacity is less than zero.</exception>
 634    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 635    public void EnsureCapacity(int capacity)
 636    {
 5637        capacity = SwiftHashTools.NextPowerOfTwo(capacity);  // Capacity must be a power of 2 for proper masking
 5638        if (capacity > _entries.Length)
 3639            Resize(capacity);
 5640    }
 641
 642    /// <summary>
 643    /// Resizes the internal arrays to the specified new size.
 644    /// </summary>
 645    /// <param name="newSize">The new size for the internal arrays.</param>
 646    private void Resize(int newSize)
 647    {
 64648        Entry[] newEntries = new Entry[newSize];
 64649        int newMask = newSize - 1;
 650
 64651        int lastIndex = 0;
 117304652        for (uint i = 0; i <= (uint)_lastIndex; i++)
 653        {
 58588654            if (_entries[i].IsUsed) // Only rehash valid entries
 655            {
 50182656                ref Entry oldEntry = ref _entries[i];
 50182657                int newIndex = oldEntry.HashCode & newMask;
 658                // If current entry not available, perform Quadratic probing to find the next available entry
 50182659                int step = 1;
 55124660                while (newEntries[newIndex].IsUsed)
 661                {
 4942662                    newIndex = (newIndex + step * step) & newMask;
 4942663                    step++;
 664                }
 50182665                newEntries[newIndex] = oldEntry;
 62648666                if (newIndex > lastIndex) lastIndex = newIndex;
 667            }
 668        }
 669
 64670        _lastIndex = lastIndex;
 671
 64672        CalculateAdaptiveResizeFactors(newSize);
 673
 64674        _entries = newEntries;
 64675        _entryMask = newMask;
 676
 64677        _version++;
 64678    }
 679
 680    /// <summary>
 681    /// Sets the capacity of a <see cref="SwiftDictionary{TKey, TValue}"/> to the actual
 682    /// number of elements it contains, rounded up to a nearby next power of 2 value.
 683    /// </summary>
 684    public void TrimExcess()
 685    {
 2686        int newSize = _count <= DefaultCapacity ? DefaultCapacity : SwiftHashTools.NextPowerOfTwo(_count);
 2687        if (newSize >= _entries.Length) return;
 688
 2689        Entry[] newEntries = new Entry[newSize];
 2690        int newMask = newSize - 1;
 691
 2692        int lastIndex = 0;
 40693        for (int i = 0; i <= (uint)_lastIndex; i++)
 694        {
 18695            if (_entries[i].IsUsed)
 696            {
 15697                ref Entry oldEntry = ref _entries[i];
 15698                int newIndex = oldEntry.HashCode & newMask;
 699                // If current entry not available, perform quadratic probing to find the next available entry
 15700                int step = 1;
 18701                while (newEntries[newIndex].IsUsed)
 702                {
 3703                    newIndex = (newIndex + step * step) & newMask;
 3704                    step++;
 705                }
 15706                newEntries[newIndex] = oldEntry;
 28707                if (newIndex > lastIndex) lastIndex = newIndex;
 708            }
 709        }
 710
 2711        _lastIndex = lastIndex;
 712
 2713        CalculateAdaptiveResizeFactors(newSize);
 714
 2715        _entryMask = newMask;
 2716        _entries = newEntries;
 717
 2718        _version++;
 2719    }
 720
 721    /// <summary>
 722    ///  Updates adaptive resize parameters based on the current fill rate to balance memory usage and performance.
 723    /// </summary>
 724    /// <param name="newSize"></param>
 725    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 726    private void CalculateAdaptiveResizeFactors(int newSize)
 727    {
 728        // Calculate current fill rate and update moving average
 66729        double currentFillRate = (double)_count / newSize;
 66730        _movingFillRate = _movingFillRate == 0 ? currentFillRate : (_movingFillRate * 0.7 + currentFillRate * 0.3);
 731
 66732        if (_movingFillRate > 0.3f)
 2733            _adaptiveResizeFactor = 2; // Growth stabilizing
 64734        else if (_movingFillRate < 0.28f)
 64735            _adaptiveResizeFactor = 4; // Rapid growth
 736
 737        // Reset the resize threshold based on the new size
 66738        _nextResizeCount = (uint)(newSize * _LoadFactorThreshold);
 66739    }
 740
 741    #endregion
 742
 743    #region Utility Methods
 744
 745    /// <summary>
 746    /// Initializes the dictionary with the specified capacity.
 747    /// </summary>
 748    /// <param name="capacity">The initial number of elements that the dictionary can contain.</param>
 749    /// <param name="comparer">The comparer to use for the dictionary.</param>
 750    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 751    [MemberNotNull(nameof(_comparer))]
 752    private void Initialize(int capacity, IEqualityComparer<TKey>? comparer = null)
 753    {
 248754        _comparer = SwiftHashTools.GetDefaultEqualityComparer(comparer);
 755
 248756        int size = capacity < DefaultCapacity ? DefaultCapacity : SwiftHashTools.NextPowerOfTwo(capacity);
 248757        _entries = new Entry[size];
 248758        _entryMask = size - 1;
 759
 248760        _nextResizeCount = (uint)(size * _LoadFactorThreshold);
 248761        _adaptiveResizeFactor = 4; // start agressive
 248762        _movingFillRate = 0.0;
 248763    }
 764
 765    /// <summary>
 766    /// Determines whether the dictionary contains an element with the specified key.
 767    /// </summary>
 768    /// <param name="key">The key to locate in the dictionary.</param>
 769    /// <returns>true if the dictionary contains an element with the specified key; otherwise, false.</returns>
 770    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 19307771    public bool ContainsKey(TKey key) => FindEntry(key) >= 0;
 772
 773    bool IDictionary.Contains(object obj)
 774    {
 4775        SwiftThrowHelper.ThrowIfNull(obj, nameof(obj));
 776
 7777        if (obj is TKey key) return ContainsKey(key);
 1778        return false;
 779    }
 780
 781    /// <inheritdoc/>
 782    public bool Contains(KeyValuePair<TKey, TValue> item)
 783    {
 2784        int index = FindEntry(item.Key);
 2785        if (index >= 0 && EqualityComparer<TValue>.Default.Equals(_entries[index].Value, item.Value))
 1786            return true;
 1787        return false;
 788    }
 789
 790    /// <inheritdoc/>
 791    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 792    public bool TryGetValue(TKey key, out TValue value)
 793    {
 8003794        int index = FindEntry(key);
 8003795        if (index >= 0)
 796        {
 7299797            value = _entries[index].Value;
 7299798            return true;
 799        }
 704800        value = default!;
 704801        return false;
 802    }
 803
 804    /// <summary>
 805    /// Copies the elements of the collection to the specified array, starting at the given array index.
 806    /// </summary>
 807    /// <param name="array">
 808    /// The one-dimensional array of key/value pairs that is the destination of the elements copied from the collection.
 809    /// The array must have zero-based indexing.
 810    /// </param>
 811    /// <param name="arrayIndex">The zero-based index in the destination array at which copying begins.</param>
 812    /// <exception cref="ArgumentOutOfRangeException">Thrown if arrayIndex is less than 0 or greater than the length of 
 813    /// <exception cref="ArgumentException">
 814    /// Thrown if the number of elements in the source collection is greater than the available space from arrayIndex to
 815    /// the end of the destination array.
 816    /// </exception>
 817    public void CopyTo(KeyValuePair<TKey, TValue>[] array, int arrayIndex)
 818    {
 14819        SwiftThrowHelper.ThrowIfNull(array, nameof(array));
 14820        SwiftThrowHelper.ThrowIfArrayIndexInvalid(arrayIndex, array.Length, message: "Array index is out of range.");
 14821        SwiftThrowHelper.ThrowIfArgument(array.Length - arrayIndex < _count, nameof(array), "Insufficient space in the t
 822
 242823        for (uint i = 0; i <= (uint)_lastIndex; i++)
 824        {
 107825            if (_entries[i].IsUsed)
 40826                array[arrayIndex++] = new KeyValuePair<TKey, TValue>(_entries[i].Key, _entries[i].Value);
 827        }
 14828    }
 829
 830    /// <inheritdoc/>
 831    public void CopyTo(Array array, int arrayIndex)
 832    {
 6833        SwiftThrowHelper.ThrowIfNull(array, nameof(array));
 6834        SwiftThrowHelper.ThrowIfArgument(array.Rank != 1, nameof(array), "Multidimensional array not supported");
 5835        SwiftThrowHelper.ThrowIfArgument(array.GetLowerBound(0) != 0, nameof(array), "Non-zero lower bound");
 4836        SwiftThrowHelper.ThrowIfArrayIndexInvalid(arrayIndex, array.Length, message: "Array index is out of range.");
 4837        SwiftThrowHelper.ThrowIfArgument(array.Length - arrayIndex < _count, nameof(array), "Insufficient space in the t
 838
 3839        if (array is KeyValuePair<TKey, TValue>[] pairs)
 0840            ((ICollection<KeyValuePair<TKey, TValue>>)this).CopyTo(pairs, arrayIndex);
 3841        else if (array is DictionaryEntry[] dictEntryArray)
 1842            CopyToDictionaryEntries(dictEntryArray, arrayIndex);
 843        else
 2844            CopyToObjects(array, arrayIndex);
 1845    }
 846
 847    private void CopyToDictionaryEntries(DictionaryEntry[] array, int arrayIndex)
 848    {
 8849        for (uint i = 0; i <= (uint)_lastIndex; i++)
 850        {
 3851            if (_entries[i].IsUsed)
 2852                array[arrayIndex++] = new DictionaryEntry(_entries[i].Key, _entries[i].Value);
 853        }
 1854    }
 855
 856    private void CopyToObjects(Array array, int arrayIndex)
 857    {
 2858        if (array is not object[] objects)
 1859            throw new ArgumentException("Invalid array type", nameof(array));
 860
 861        try
 862        {
 1863            CopyToObjects(objects, arrayIndex);
 1864        }
 0865        catch (ArrayTypeMismatchException)
 866        {
 0867            throw new ArgumentException("Invalid array type", nameof(array));
 868        }
 1869    }
 870
 871    private void CopyToObjects(object[] array, int arrayIndex)
 872    {
 8873        for (uint i = 0; i <= (uint)_lastIndex; i++)
 874        {
 3875            if (_entries[i].IsUsed)
 2876                array[arrayIndex++] = new KeyValuePair<TKey, TValue>(_entries[i].Key, _entries[i].Value);
 877        }
 1878    }
 879
 880    /// <summary>
 881    /// Sets a new comparer for the dictionary and rehashes the entries.
 882    /// </summary>
 883    /// <param name="comparer">The new comparer to use.</param>
 884    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 885    public void SetComparer(IEqualityComparer<TKey> comparer)
 886    {
 4887        SwiftThrowHelper.ThrowIfNull(comparer, nameof(comparer));
 4888        if (ReferenceEquals(comparer, _comparer))
 0889            return;
 890
 4891        _comparer = comparer;
 4892        RehashEntries();
 4893        _maxStepCount = 0;
 4894    }
 895
 896    /// <summary>
 897    /// Switches the dictionary's comparer to a randomized comparer to mitigate the effects of high collision counts,
 898    /// and rehashes all entries using the new comparer to redistribute them across <see cref="_entries"/>.
 899    /// </summary>
 900    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 901    private void SwitchToRandomizedComparer()
 902    {
 1903        if (SwiftHashTools.IsWellKnownEqualityComparer(_comparer))
 1904            _comparer = (IEqualityComparer<TKey>)SwiftHashTools.GetSwiftEqualityComparer(_comparer);
 0905        else return; // nothing to do here
 906
 1907        RehashEntries();
 1908        _maxStepCount = 0;
 909
 1910        _version++;
 1911    }
 912
 913    /// <summary>
 914    /// Reconstructs the internal entry structure to align with updated hash codes, ensuring efficient access and storag
 915    /// </summary>
 916    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 917    private void RehashEntries()
 918    {
 5919        Entry[] newEntries = new Entry[_entries.Length];
 5920        int newMask = newEntries.Length - 1;
 921
 5922        int lastIndex = 0;
 612923        for (uint i = 0; i <= (uint)_lastIndex; i++)
 924        {
 301925            if (_entries[i].IsUsed)
 926            {
 109927                ref Entry oldEntry = ref _entries[i];
 109928                oldEntry.HashCode = _comparer.GetHashCode(oldEntry.Key) & 0x7FFFFFFF;
 109929                int newIndex = oldEntry.HashCode & newMask;
 109930                int step = 1;
 121931                while (newEntries[newIndex].IsUsed)
 932                {
 12933                    newIndex = (newIndex + step * step) & newMask; // Quadratic probing
 12934                    step++;
 935                }
 109936                newEntries[newIndex] = _entries[i];
 131937                if (newIndex > lastIndex) lastIndex = newIndex;
 938            }
 939        }
 940
 5941        _lastIndex = lastIndex;
 942
 5943        _entryMask = newMask;
 5944        _entries = newEntries;
 945
 5946        _version++;
 5947    }
 948
 949    /// <summary>
 950    /// Finds the arrayIndex of the entry with the specified key.
 951    /// </summary>
 952    /// <param name="key">The key to locate in the dictionary.</param>
 953    /// <returns>The arrayIndex of the entry if found; otherwise, -1.</returns>
 954    /// <exception cref="ArgumentNullException">The key is null.</exception>
 955    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 956    protected int FindEntry(TKey key)
 957    {
 41328958        if (key == null) return -1;
 959
 41328960        int hashCode = _comparer.GetHashCode(key) & 0x7FFFFFFF;
 41328961        int entryIndex = hashCode & _entryMask;
 962
 41328963        int step = 0;
 46804964        while ((uint)step <= (uint)_lastIndex)
 965        {
 46793966            ref Entry entry = ref _entries[entryIndex];
 967            // Stop probing if an unused entry is found (not deleted)
 46793968            if (!entry.IsUsed && entry.HashCode != -1)
 18275969                return -1;
 28518970            if (entry.IsUsed && entry.HashCode == hashCode && _comparer.Equals(entry.Key, key))
 23042971                return entryIndex; // Match found
 972
 973            // Perform quadratic probing to see if maybe the entry was shifted.
 5476974            step++;
 5476975            entryIndex = (entryIndex + step * step) & _entryMask;
 976        }
 11977        return -1; // Item not found, full loop completed
 978    }
 979
 980    #endregion
 981
 982    #region IEnumerable Implementation
 983
 984    /// <inheritdoc cref="IEnumerable.GetEnumerator()"/>
 32985    public SwiftDictionaryEnumerator GetEnumerator() => new(this);
 22986    IEnumerator<KeyValuePair<TKey, TValue>> IEnumerable<KeyValuePair<TKey, TValue>>.GetEnumerator() => GetEnumerator();
 1987    IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
 3988    IDictionaryEnumerator IDictionary.GetEnumerator() => new SwiftDictionaryEnumerator(this, true);
 989
 990    /// <summary>
 991    /// Provides an efficient enumerator for iterating over the key-value pairs in the SwiftDictionary, enabling smooth 
 992    /// </summary>
 993    [Serializable]
 994    public struct SwiftDictionaryEnumerator : IEnumerator<KeyValuePair<TKey, TValue>>, IEnumerator, IDictionaryEnumerato
 995    {
 996        private readonly SwiftDictionary<TKey, TValue> _dictionary;
 997        private readonly Entry[] _entries;
 998        private readonly uint _version;
 999        private readonly bool _returnEntry;
 1000        private int _index;
 1001        private KeyValuePair<TKey, TValue> _current;
 1002
 1003        internal SwiftDictionaryEnumerator(SwiftDictionary<TKey, TValue> dictionary, bool returnEntry = false)
 1004        {
 351005            _dictionary = dictionary;
 351006            _entries = dictionary._entries;
 351007            _version = dictionary._version;
 351008            _returnEntry = returnEntry;
 351009            _index = -1;
 351010            _current = default;
 351011        }
 1012
 1013        object IDictionaryEnumerator.Key
 1014        {
 1015            get
 1016            {
 31017                SwiftThrowHelper.ThrowIfTrue(_index > (uint)_dictionary._lastIndex, message: "Enumerator is positioned b
 31018                return _current.Key;
 1019            }
 1020        }
 1021
 1022        object IDictionaryEnumerator.Value
 1023        {
 1024            get
 1025            {
 11026                SwiftThrowHelper.ThrowIfTrue(_index > (uint)_dictionary._lastIndex, message: "Enumerator is positioned b
 11027                return _current.Value!;
 1028            }
 1029        }
 1030
 1031        DictionaryEntry IDictionaryEnumerator.Entry
 1032        {
 1033            get
 1034            {
 21035                SwiftThrowHelper.ThrowIfTrue(_index > (uint)_dictionary._lastIndex, message: "Enumerator is positioned b
 11036                return new DictionaryEntry(_current.Key, _current.Value);
 1037            }
 1038        }
 1039
 1040        /// <inheritdoc/>
 501041        public KeyValuePair<TKey, TValue> Current => _current;
 1042
 1043        object IEnumerator.Current
 1044        {
 1045            get
 1046            {
 21047                SwiftThrowHelper.ThrowIfTrue(_index > (uint)_dictionary._lastIndex, message: "Enumerator is positioned b
 21048                return _returnEntry
 21049                    ? new DictionaryEntry(_current.Key, _current.Value)
 21050                    : new KeyValuePair<TKey, TValue>(_current.Key, _current.Value);
 1051            }
 1052        }
 1053
 1054        /// <inheritdoc/>
 1055        public bool MoveNext()
 1056        {
 791057            SwiftThrowHelper.ThrowIfTrue(_version != _dictionary._version, message: "Enumerator modified outside of enum
 1058
 1571059            while (++_index <= (uint)_dictionary._lastIndex)
 1060            {
 1241061                if (_entries[_index].IsUsed)
 1062                {
 461063                    _current = new KeyValuePair<TKey, TValue>(_entries[_index].Key, _entries[_index].Value);
 461064                    return true;
 1065                }
 1066            }
 1067
 331068            _current = default;
 331069            return false;
 1070        }
 1071
 1072        /// <inheritdoc/>
 1073        public void Reset()
 1074        {
 11075            SwiftThrowHelper.ThrowIfTrue(_version != _dictionary._version, message: "Enumerator modified outside of enum
 1076
 11077            _index = -1;
 11078            _current = default;
 11079        }
 1080
 1081        /// <inheritdoc/>
 321082        public void Dispose() => _index = -1;
 1083    }
 1084
 1085    #endregion
 1086
 1087    #region Key & Value Collections
 1088
 1089    /// <summary>
 1090    /// Provides a dynamic, read-only collection of all keys in the dictionary, supporting enumeration and copy operatio
 1091    /// </summary>
 1092    [Serializable]
 1093    public sealed class KeyCollection : ICollection<TKey>, ICollection, IReadOnlyCollection<TKey>, IEnumerable<TKey>, IE
 1094    {
 1095        private readonly SwiftDictionary<TKey, TValue> _dictionary;
 1096        private readonly Entry[] _entries;
 1097
 1098        /// <summary>
 1099        /// Initializes a new instance of the KeyCollection class that reflects the keys in the specified dictionary.
 1100        /// </summary>
 1101        /// <param name="dictionary">The dictionary whose keys are reflected in the new KeyCollection.</param>
 1102        /// <exception cref="ArgumentNullException">The dictionary is null.</exception>
 131103        public KeyCollection(SwiftDictionary<TKey, TValue> dictionary)
 1104        {
 131105            SwiftThrowHelper.ThrowIfNull(dictionary, nameof(dictionary));
 131106            _dictionary = dictionary;
 131107            _entries = dictionary._entries;
 131108        }
 1109
 1110        /// <inheritdoc/>
 11111        public int Count => _dictionary._count;
 1112
 11113        bool ICollection.IsSynchronized => false;
 1114
 11115        object ICollection.SyncRoot => ((ICollection)_dictionary).SyncRoot;
 1116
 11117        bool ICollection<TKey>.IsReadOnly => true;
 1118
 11119        void ICollection<TKey>.Add(TKey item) => throw new NotSupportedException();
 1120
 11121        void ICollection<TKey>.Clear() => throw new NotSupportedException();
 1122
 21123        bool ICollection<TKey>.Contains(TKey item) => _dictionary.ContainsKey(item);
 1124
 11125        bool ICollection<TKey>.Remove(TKey item) => false;
 1126
 1127        /// <inheritdoc/>
 1128        public void CopyTo(TKey[] array, int arrayIndex)
 1129        {
 11130            SwiftThrowHelper.ThrowIfNull(array, nameof(array));
 11131            SwiftThrowHelper.ThrowIfArrayIndexInvalid(arrayIndex, array.Length, message: "Array index is out of range.")
 11132            SwiftThrowHelper.ThrowIfArgument(array.Length - arrayIndex < _dictionary._count, nameof(array), "Insufficien
 1133
 191134            for (int i = 0, j = arrayIndex; i < _entries.Length; i++)
 1135            {
 81136                if (_entries[i].IsUsed)
 21137                    array[j++] = _entries[i].Key;
 1138            }
 11139        }
 1140
 1141        void ICollection.CopyTo(Array array, int arrayIndex)
 1142        {
 21143            SwiftThrowHelper.ThrowIfNull(array, nameof(array));
 21144            SwiftThrowHelper.ThrowIfArgument(array.Rank != 1, nameof(array), "Multidimensional array not supported");
 21145            SwiftThrowHelper.ThrowIfArgument(array.GetLowerBound(0) != 0, nameof(array), "Non-zero lower bound");
 21146            SwiftThrowHelper.ThrowIfArrayIndexInvalid(arrayIndex, array.Length, message: "Array index is out of range.")
 21147            SwiftThrowHelper.ThrowIfArgument(array.Length - arrayIndex < _dictionary._count, nameof(array), "Insufficien
 1148
 21149            if (array is TKey[] keysArray)
 01150                CopyTo(keysArray, arrayIndex);
 21151            else if (array is object[] objects)
 1152            {
 1153                try
 1154                {
 241155                    for (int i = 0, j = arrayIndex; i < _entries.Length; i++)
 1156                    {
 101157                        if (_entries[i].IsUsed)
 31158                            objects[j++] = _entries[i].Key;
 1159                    }
 11160                }
 11161                catch (ArrayTypeMismatchException)
 1162                {
 11163                    throw new ArgumentException("Invalid array type", nameof(array));
 1164                }
 1165            }
 1166            else
 1167            {
 01168                throw new ArgumentException("Invalid array type", nameof(array));
 1169            }
 11170        }
 1171
 1172        /// <summary>
 1173        /// Returns an enumerator that iterates through the keys in the collection.
 1174        /// </summary>
 1175        /// <returns>An enumerator for the keys in the collection.</returns>
 91176        public KeyCollectionEnumerator GetEnumerator() => new(_dictionary);
 71177        IEnumerator<TKey> IEnumerable<TKey>.GetEnumerator() => GetEnumerator();
 21178        IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
 1179
 1180        /// <summary>
 1181        /// Enumerates the keys of a <see cref="SwiftDictionary{TKey, TValue}"/> collection.
 1182        /// </summary>
 1183        /// <remarks>
 1184        /// The enumerator provides read-only, forward-only iteration over the keys in the dictionary.
 1185        /// The enumerator is invalidated if the dictionary is modified after the enumerator is created.
 1186        /// In such cases, calling MoveNext or Reset will throw an InvalidOperationException.
 1187        /// </remarks>
 1188        [Serializable]
 1189        public struct KeyCollectionEnumerator : IEnumerator<TKey>, IEnumerator, IDisposable
 1190        {
 1191            private readonly SwiftDictionary<TKey, TValue> _dictionary;
 1192            private readonly Entry[] _entries;
 1193            private readonly uint _version;
 1194            private int _index;
 1195            private TKey _currentKey;
 1196
 1197            internal KeyCollectionEnumerator(SwiftDictionary<TKey, TValue> dictionary)
 1198            {
 91199                _dictionary = dictionary;
 91200                _entries = dictionary._entries;
 91201                _version = dictionary._version;
 91202                _index = -1;
 91203                _currentKey = default!;
 91204            }
 1205
 1206            /// <inheritdoc/>
 241207            public TKey Current => _currentKey;
 1208
 1209            object IEnumerator.Current
 1210            {
 1211                get
 1212                {
 11213                    SwiftThrowHelper.ThrowIfTrue(_index > (uint)_dictionary._lastIndex, message: "Enumerator is position
 11214                    return _currentKey;
 1215                }
 1216            }
 1217
 1218            /// <inheritdoc/>
 1219            public bool MoveNext()
 1220            {
 251221                SwiftThrowHelper.ThrowIfTrue(_version != _dictionary._version, message: "Enumerator modified outside of 
 1222
 491223                while (++_index <= (uint)_dictionary._lastIndex)
 1224                {
 451225                    if (_entries[_index].IsUsed)
 1226                    {
 201227                        _currentKey = _entries[_index].Key;
 201228                        return true;
 1229                    }
 1230                }
 1231
 41232                _currentKey = default!;
 41233                return false;
 1234            }
 1235
 1236            /// <inheritdoc/>
 1237            public void Reset()
 1238            {
 11239                SwiftThrowHelper.ThrowIfTrue(_version != _dictionary._version, message: "Enumerator modified outside of 
 1240
 11241                _index = -1;
 11242                _currentKey = default!;
 11243            }
 1244
 1245            /// <inheritdoc/>
 71246            public void Dispose() => _index = -1;
 1247        }
 1248    }
 1249
 1250    /// <summary>
 1251    /// Offers a dynamic, read-only collection of all values in the dictionary, supporting enumeration and copy operatio
 1252    /// </summary>
 1253    [Serializable]
 1254    public sealed class ValueCollection : ICollection<TValue>, ICollection, IReadOnlyCollection<TValue>, IEnumerable<TVa
 1255    {
 1256        private readonly SwiftDictionary<TKey, TValue> _dictionary;
 1257        private readonly Entry[] _entries;
 1258
 1259        /// <summary>
 1260        /// Initializes a new instance of the ValueCollection class that reflects the values in the specified dictionary
 1261        /// </summary>
 1262        /// <param name="dictionary">The dictionary whose values are reflected in the new ValueCollection.</param>
 1263        /// <exception cref="ArgumentNullException">The dictionary is null.</exception>
 91264        public ValueCollection(SwiftDictionary<TKey, TValue> dictionary)
 1265        {
 91266            SwiftThrowHelper.ThrowIfNull(dictionary, nameof(dictionary));
 91267            _dictionary = dictionary;
 91268            _entries = dictionary._entries;
 91269        }
 1270
 1271        /// <inheritdoc/>
 11272        public int Count => _dictionary._count;
 1273
 11274        bool ICollection<TValue>.IsReadOnly => true;
 1275
 11276        bool ICollection.IsSynchronized => false;
 1277
 11278        object ICollection.SyncRoot => ((ICollection)_dictionary).SyncRoot;
 1279
 11280        void ICollection<TValue>.Add(TValue item) => throw new NotSupportedException();
 1281
 11282        void ICollection<TValue>.Clear() => throw new NotSupportedException();
 1283
 1284        bool ICollection<TValue>.Contains(TValue item)
 1285        {
 121286            for (uint i = 0; i <= (uint)_dictionary._lastIndex; i++)
 1287            {
 61288                if (_entries[i].IsUsed && EqualityComparer<TValue>.Default.Equals(_entries[i].Value, item))
 21289                    return true;
 1290            }
 01291            return false;
 1292        }
 1293
 11294        bool ICollection<TValue>.Remove(TValue item) => false;
 1295
 1296        /// <inheritdoc/>
 1297        public void CopyTo(TValue[] array, int arrayIndex)
 1298        {
 11299            SwiftThrowHelper.ThrowIfNull(array, nameof(array));
 11300            SwiftThrowHelper.ThrowIfArrayIndexInvalid(arrayIndex, array.Length, message: "Array index is out of range.")
 11301            SwiftThrowHelper.ThrowIfArgument(array.Length - arrayIndex < _dictionary._count, nameof(array), "Insufficien
 1302
 91303            for (int i = 0, j = arrayIndex; i <= _dictionary._lastIndex; i++)
 1304            {
 31305                if (_dictionary._entries[i].IsUsed)
 21306                    array[j++] = _entries[i].Value;
 1307            }
 11308        }
 1309
 1310        void ICollection.CopyTo(Array array, int arrayIndex)
 1311        {
 21312            SwiftThrowHelper.ThrowIfNull(array, nameof(array));
 21313            SwiftThrowHelper.ThrowIfArgument(array.Rank != 1, nameof(array), "Multidimensional array not supported");
 21314            SwiftThrowHelper.ThrowIfArgument(array.GetLowerBound(0) != 0, nameof(array), "Non-zero lower bound");
 21315            SwiftThrowHelper.ThrowIfArrayIndexInvalid(arrayIndex, array.Length, message: "Array index is out of range.")
 21316            SwiftThrowHelper.ThrowIfArgument(array.Length - arrayIndex < _dictionary._count, nameof(array), "Insufficien
 1317
 21318            if (array is TValue[] valuesArray)
 01319                CopyTo(valuesArray, arrayIndex);
 21320            else if (array is object[] objects)
 1321            {
 1322                try
 1323                {
 91324                    for (int i = 0, j = arrayIndex; i <= _dictionary._lastIndex; i++)
 31325                        if (_entries[i].IsUsed)
 21326                            objects[j++] = _entries[i].Value!;
 11327                }
 01328                catch (ArrayTypeMismatchException)
 1329                {
 01330                    throw new ArgumentException("Invalid array type", nameof(array));
 1331                }
 1332            }
 11333            else throw new ArgumentException("Invalid array type", nameof(array));
 11334        }
 1335
 1336        /// <summary>
 1337        /// Returns an enumerator that iterates through the values in the collection.
 1338        /// </summary>
 1339        /// <returns>An enumerator for the values in the collection.</returns>
 51340        public ValueCollectionEnumerator GetEnumerator() => new(_dictionary);
 31341        IEnumerator<TValue> IEnumerable<TValue>.GetEnumerator() => GetEnumerator();
 21342        IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
 1343
 1344        /// <summary>
 1345        /// Enumerates the values in a SwiftDictionary collection.
 1346        /// </summary>
 1347        /// <remarks>
 1348        /// The enumerator is invalidated if the collection is modified after the enumerator is created.
 1349        /// Enumerators are typically used in a foreach statement to iterate through the collection values.
 1350        /// </remarks>
 1351        [Serializable]
 1352        public struct ValueCollectionEnumerator : IEnumerator<TValue>, IEnumerator, IDisposable
 1353        {
 1354            private readonly SwiftDictionary<TKey, TValue> _dictionary;
 1355            private readonly Entry[] _entries;
 1356            private readonly uint _version;
 1357            private int _index;
 1358            private TValue _currentValue;
 1359
 1360            internal ValueCollectionEnumerator(SwiftDictionary<TKey, TValue> dictionary)
 1361            {
 51362                _dictionary = dictionary;
 51363                _entries = dictionary._entries;
 51364                _version = dictionary._version;
 51365                _index = -1;
 51366                _currentValue = default!;
 51367            }
 1368
 1369            /// <inheritdoc/>
 121370            public TValue Current => _currentValue;
 1371
 1372            object IEnumerator.Current
 1373            {
 1374                get
 1375                {
 11376                    SwiftThrowHelper.ThrowIfTrue(_index > (uint)_dictionary._lastIndex, message: "Enumerator is position
 11377                    return _currentValue!;
 1378                }
 1379            }
 1380
 1381            /// <inheritdoc/>
 1382            public bool MoveNext()
 1383            {
 91384                SwiftThrowHelper.ThrowIfTrue(_version != _dictionary._version, message: "Enumerator modified outside of 
 1385
 131386                while (++_index <= (uint)_dictionary._lastIndex)
 1387                {
 131388                    if (_entries[_index].IsUsed)
 1389                    {
 81390                        _currentValue = _entries[_index].Value;
 81391                        return true;
 1392                    }
 1393                }
 1394
 01395                _currentValue = default!;
 01396                return false;
 1397            }
 1398
 1399            /// <inheritdoc/>
 1400            public void Reset()
 1401            {
 11402                SwiftThrowHelper.ThrowIfTrue(_version != _dictionary._version, message: "Enumerator modified outside of 
 1403
 11404                _index = -1;
 11405                _currentValue = default!;
 11406            }
 1407
 1408            /// <inheritdoc/>
 31409            public void Dispose() => _index = -1;
 1410        }
 1411    }
 1412
 1413    #endregion
 1414}

Methods/Properties

.ctor()
.ctor(System.Int32,System.Collections.Generic.IEqualityComparer`1<TKey>)
.ctor(System.Collections.Generic.IDictionary`2<TKey,TValue>,System.Collections.Generic.IEqualityComparer`1<TKey>)
.ctor(System.Collections.Generic.IEnumerable`1<System.Collections.Generic.KeyValuePair`2<TKey,TValue>>,System.Collections.Generic.IEqualityComparer`1<TKey>)
.ctor(SwiftCollections.SwiftDictionaryState`2<TKey,TValue>)
get_Count()
get_Capacity()
get_Comparer()
get_Item(TKey)
set_Item(TKey,TValue)
System.Collections.IDictionary.get_Item(System.Object)
System.Collections.IDictionary.set_Item(System.Object,System.Object)
get_Keys()
System.Collections.IDictionary.get_Keys()
get_Values()
System.Collections.IDictionary.get_Values()
System.Collections.Generic.ICollection<System.Collections.Generic.KeyValuePair<TKey,TValue>>.get_IsReadOnly()
System.Collections.IDictionary.get_IsReadOnly()
System.Collections.IDictionary.get_IsFixedSize()
System.Collections.ICollection.get_IsSynchronized()
get_SyncRoot()
get_State()
set_State(SwiftCollections.SwiftDictionaryState`2<TKey,TValue>)
Add(TKey,TValue)
Add(System.Collections.Generic.KeyValuePair`2<TKey,TValue>)
System.Collections.Generic.IDictionary<TKey,TValue>.Add(TKey,TValue)
Add(System.Object,System.Object)
InsertIfNotExist(TKey,TValue)
Remove(TKey)
System.Collections.IDictionary.Remove(System.Object)
Remove(System.Collections.Generic.KeyValuePair`2<TKey,TValue>)
Clear()
CheckLoadThreshold()
EnsureCapacity(System.Int32)
Resize(System.Int32)
TrimExcess()
CalculateAdaptiveResizeFactors(System.Int32)
Initialize(System.Int32,System.Collections.Generic.IEqualityComparer`1<TKey>)
ContainsKey(TKey)
System.Collections.IDictionary.Contains(System.Object)
Contains(System.Collections.Generic.KeyValuePair`2<TKey,TValue>)
TryGetValue(TKey,TValue&)
CopyTo(System.Collections.Generic.KeyValuePair`2<TKey,TValue>[],System.Int32)
CopyTo(System.Array,System.Int32)
CopyToDictionaryEntries(System.Collections.DictionaryEntry[],System.Int32)
CopyToObjects(System.Array,System.Int32)
CopyToObjects(System.Object[],System.Int32)
SetComparer(System.Collections.Generic.IEqualityComparer`1<TKey>)
SwitchToRandomizedComparer()
RehashEntries()
FindEntry(TKey)
GetEnumerator()
System.Collections.Generic.IEnumerable<System.Collections.Generic.KeyValuePair<TKey,TValue>>.GetEnumerator()
System.Collections.IEnumerable.GetEnumerator()
System.Collections.IDictionary.GetEnumerator()
.ctor(SwiftCollections.SwiftDictionary`2<TKey,TValue>,System.Boolean)
System.Collections.IDictionaryEnumerator.get_Key()
System.Collections.IDictionaryEnumerator.get_Value()
System.Collections.IDictionaryEnumerator.get_Entry()
get_Current()
System.Collections.IEnumerator.get_Current()
MoveNext()
Reset()
Dispose()
.ctor(SwiftCollections.SwiftDictionary`2<TKey,TValue>)
get_Count()
System.Collections.ICollection.get_IsSynchronized()
System.Collections.ICollection.get_SyncRoot()
System.Collections.Generic.ICollection<TKey>.get_IsReadOnly()
System.Collections.Generic.ICollection<TKey>.Add(TKey)
System.Collections.Generic.ICollection<TKey>.Clear()
System.Collections.Generic.ICollection<TKey>.Contains(TKey)
System.Collections.Generic.ICollection<TKey>.Remove(TKey)
CopyTo(TKey[],System.Int32)
System.Collections.ICollection.CopyTo(System.Array,System.Int32)
GetEnumerator()
System.Collections.Generic.IEnumerable<TKey>.GetEnumerator()
System.Collections.IEnumerable.GetEnumerator()
.ctor(SwiftCollections.SwiftDictionary`2<TKey,TValue>)
get_Current()
System.Collections.IEnumerator.get_Current()
MoveNext()
Reset()
Dispose()
.ctor(SwiftCollections.SwiftDictionary`2<TKey,TValue>)
get_Count()
System.Collections.Generic.ICollection<TValue>.get_IsReadOnly()
System.Collections.ICollection.get_IsSynchronized()
System.Collections.ICollection.get_SyncRoot()
System.Collections.Generic.ICollection<TValue>.Add(TValue)
System.Collections.Generic.ICollection<TValue>.Clear()
System.Collections.Generic.ICollection<TValue>.Contains(TValue)
System.Collections.Generic.ICollection<TValue>.Remove(TValue)
CopyTo(TValue[],System.Int32)
System.Collections.ICollection.CopyTo(System.Array,System.Int32)
GetEnumerator()
System.Collections.Generic.IEnumerable<TValue>.GetEnumerator()
System.Collections.IEnumerable.GetEnumerator()
.ctor(SwiftCollections.SwiftDictionary`2<TKey,TValue>)
get_Current()
System.Collections.IEnumerator.get_Current()
MoveNext()
Reset()
Dispose()