< Summary

Class:KeyValueSetPair[TKey,TValue]
Assembly:KeyValueSet
File(s):/tmp/workspace/unity-renderer/unity-renderer/Assets/Scripts/MainScripts/DCL/Helpers/Utils/KeyValueSet/KeyValueSet.cs
Covered lines:3
Uncovered lines:0
Coverable lines:3
Total lines:150
Line coverage:100% (3 of 3)
Covered branches:0
Total branches:0

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity NPath complexity Sequence coverage
KeyValueSetPair(...)0%110100%

File(s)

/tmp/workspace/unity-renderer/unity-renderer/Assets/Scripts/MainScripts/DCL/Helpers/Utils/KeyValueSet/KeyValueSet.cs

#LineLine coverage
 1using System;
 2using System.Collections;
 3using System.Collections.Generic;
 4
 5/*
 6 * `KeyValueSet` works as an alternative of `Dictionary` when a iteration through all it values is performed frequently.
 7 * CONS: It's much slower to modify the data compared to a `Dictionary`
 8 * PRO: It's much faster to iterate through all the data compared to a `Dictionary` and
 9 *      it doesn't alloc extra memory while doing so.
 10 * Benchmark against a `Dictionary`:
 11 * Adding element: ~32% slower
 12 * Removing element: ~164% slower
 13 * Iterating through all elements: ~34% faster
 14 */
 15
 16public readonly struct KeyValueSetPair<TKey, TValue>
 17{
 18    public readonly TKey key;
 19    public readonly TValue value;
 20
 21    public KeyValueSetPair(TKey key, TValue value)
 22    {
 91823        this.key = key;
 91824        this.value = value;
 91825    }
 26}
 27
 28public interface IReadOnlyKeyValueSet<TKey, TValue> : IEnumerable<KeyValueSetPair<TKey, TValue>>
 29{
 30    TValue this[TKey key] { get; }
 31    int Count { get; }
 32    IReadOnlyList<KeyValueSetPair<TKey, TValue>> Pairs { get; }
 33    bool ContainsKey(TKey key);
 34    bool TryGetValue(TKey key, out TValue value);
 35}
 36
 37public class KeyValueSet<TKey, TValue> : IReadOnlyKeyValueSet<TKey, TValue>
 38{
 39    private readonly Dictionary<TKey, int> indexer;
 40    private readonly List<KeyValueSetPair<TKey, TValue>> pairs;
 41
 42    public IReadOnlyList<KeyValueSetPair<TKey, TValue>> Pairs => pairs;
 43
 44    public int Count => pairs.Count;
 45
 46    public TValue this[TKey key]
 47    {
 48        set => AddInternal(key, value, false);
 49        get
 50        {
 51            TryGetValue(key, out TValue value);
 52            return value;
 53        }
 54    }
 55
 56    public KeyValueSet() : this(0) { }
 57
 58    public KeyValueSet(int capacity)
 59    {
 60        indexer = new Dictionary<TKey, int>(capacity);
 61        pairs = new List<KeyValueSetPair<TKey, TValue>>(capacity);
 62    }
 63
 64    public bool ContainsKey(TKey key)
 65    {
 66        return indexer.ContainsKey(key);
 67    }
 68
 69    public bool TryGetValue(TKey key, out TValue value)
 70    {
 71        if (!indexer.TryGetValue(key, out int index))
 72        {
 73            value = default;
 74            return false;
 75        }
 76        value = pairs[index].value;
 77        return true;
 78    }
 79
 80    public void Add(TKey key, TValue value)
 81    {
 82        AddInternal(key, value, true);
 83    }
 84
 85    public void RemoveAt(int index)
 86    {
 87        int count = Count;
 88        if (index >= count || index < 0)
 89        {
 90            throw new IndexOutOfRangeException();
 91        }
 92
 93        TKey key = pairs[index].key;
 94
 95        if (count > 1 && index < count - 1)
 96        {
 97            int lastValueIndex = count - 1;
 98            pairs[index] = pairs[lastValueIndex];
 99            indexer[pairs[lastValueIndex].key] = index;
 100            pairs.RemoveAt(lastValueIndex);
 101        }
 102        else
 103        {
 104            pairs.RemoveAt(index);
 105        }
 106
 107        indexer.Remove(key);
 108    }
 109
 110    public bool Remove(TKey key)
 111    {
 112        if (!indexer.TryGetValue(key, out int index))
 113        {
 114            return false;
 115        }
 116
 117        RemoveAt(index);
 118        return true;
 119    }
 120
 121    public void Clear()
 122    {
 123        indexer.Clear();
 124        pairs.Clear();
 125    }
 126
 127    public IEnumerator<KeyValueSetPair<TKey, TValue>> GetEnumerator()
 128    {
 129        for (int i = 0; i < Count; i++)
 130        {
 131            yield return pairs[i];
 132        }
 133    }
 134
 135    IEnumerator IEnumerable.GetEnumerator()
 136    {
 137        return GetEnumerator();
 138    }
 139
 140    private void AddInternal(TKey key, TValue value, bool add)
 141    {
 142        if (!add && indexer.TryGetValue(key, out int index))
 143        {
 144            pairs[index] = new KeyValueSetPair<TKey, TValue>(key, value);
 145            return;
 146        }
 147        indexer.Add(key, pairs.Count);
 148        pairs.Add(new KeyValueSetPair<TKey, TValue>(key, value));
 149    }
 150}

Methods/Properties

KeyValueSetPair(TKey, TValue)