File: ValueEqualityImmutableDictionary.cs
Web Access
Project: src\src\libraries\System.Runtime.InteropServices\gen\Microsoft.Interop.SourceGeneration\Microsoft.Interop.SourceGeneration.csproj (Microsoft.Interop.SourceGeneration)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
 
using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.Immutable;
 
namespace Microsoft.Interop
{
    public record struct ValueEqualityImmutableDictionary<T, U>(ImmutableDictionary<T, U> Map) : IDictionary<T, U>
    {
        // Since this is immutable, we can cache the hash, which requires sorting and is expensive to calculate
        private int? _hash = null;
 
        public bool Equals(ValueEqualityImmutableDictionary<T, U> other)
        {
            if (Count != other.Count)
            {
                return false;
            }
 
            foreach (var kvp in this)
            {
                if (!other.TryGetValue(kvp.Key, out var value) || !kvp.Value.Equals(value))
                {
                    return false;
                }
            }
            return true;
        }
 
        public override int GetHashCode()
        {
            if (_hash.HasValue)
                return _hash.Value;
 
            _hash = 0;
            foreach (var kvp in Map.ToImmutableArray().Sort())
            {
                _hash = HashCode.Combine(_hash, kvp.Key, kvp.Value);
            }
            return _hash.Value;
        }
 
        public U this[T key] { get => ((IDictionary<T, U>)Map)[key]; set => ((IDictionary<T, U>)Map)[key] = value; }
        public ICollection<T> Keys => ((IDictionary<T, U>)Map).Keys;
        public ICollection<U> Values => ((IDictionary<T, U>)Map).Values;
        public int Count => Map.Count;
        public bool IsReadOnly => ((ICollection<KeyValuePair<T, U>>)Map).IsReadOnly;
        public bool Contains(KeyValuePair<T, U> item) => Map.Contains(item);
        public bool ContainsKey(T key) => Map.ContainsKey(key);
        public void CopyTo(KeyValuePair<T, U>[] array, int arrayIndex) => ((ICollection<KeyValuePair<T, U>>)Map).CopyTo(array, arrayIndex);
        public IEnumerator<KeyValuePair<T, U>> GetEnumerator() => ((IEnumerable<KeyValuePair<T, U>>)Map).GetEnumerator();
        public bool Remove(T key) => ((IDictionary<T, U>)Map).Remove(key);
        public bool Remove(KeyValuePair<T, U> item) => ((ICollection<KeyValuePair<T, U>>)Map).Remove(item);
        public bool TryGetValue(T key, out U value) => Map.TryGetValue(key, out value);
        IEnumerator IEnumerable.GetEnumerator() => ((IEnumerable)Map).GetEnumerator();
        public void Add(T key, U value) => ((IDictionary<T, U>)Map).Add(key, value);
        public void Add(KeyValuePair<T, U> item) => ((ICollection<KeyValuePair<T, U>>)Map).Add(item);
        public void Clear() => ((ICollection<KeyValuePair<T, U>>)Map).Clear();
    }
 
    public static class ValueEqualityImmutableDictionaryHelperExtensions
    {
        public static ValueEqualityImmutableDictionary<TKey, TValue> ToValueEqualityImmutableDictionary<TSource, TKey, TValue>(
            this IEnumerable<TSource> source,
            Func<TSource, TKey> keySelector,
            Func<TSource, TValue> valueSelector)
        {
            return new ValueEqualityImmutableDictionary<TKey, TValue>(source.ToImmutableDictionary(keySelector, valueSelector));
        }
        public static ValueEqualityImmutableDictionary<TKey, TValue> ToValueEquals<TKey, TValue>(this ImmutableDictionary<TKey, TValue> source)
        {
            return new ValueEqualityImmutableDictionary<TKey, TValue>(source);
        }
 
    }
}