0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

C#でenumをキーにした高速Dictionaryを考え中。

Last updated at Posted at 2019-06-15

C# で以下の様な、初期化して読み出すだけの enum の Dictionary を作りたい場合、通常の Dictionary はメモリ効率や処理速度の点で効率が悪いので、単純なものが欲しかったので考えてみました。

以下のような使い方が出来ればそれだけでいい。

    enum EnumAlpha
    {
        A,
        B,
    }
    Dictionary<EnumAlpha, StructAB> dic1 = new Dictionary<EnumAlpha, StructAB>()
    {
        {EnumAlpha.A, "A"},
        {EnumAlpha.B, "B"}
    };

enumだけをキーとして使うDictionaryクラス。
中はテーブルで、enum の個数分あらかじめ確保しています。
取り出しがめっちゃ速いはず。

ENumDictionay.cs

class ENumDictionary<TKey, TValue> : IEnumerable<KeyValuePair<TKey, TValue>> where TKey : struct, IConvertible
{
    private TValue[] array = null;

    public ENumDictionary()
    {
        int length = Enum.GetNames(typeof(TKey)).Length;
        array = new TValue[length];
    }

    public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator()
    {
        return new MyEnumerator(this);
    }

    IEnumerator IEnumerable.GetEnumerator()
    {
        return GetEnumerator();
    }

    public TValue this[TKey key]
    {
        set
        {
            array[KeyToIndex(key)] = value;
        }
        get
        {
            return array[KeyToIndex(key)];
        }
    }

    private static int KeyToIndex(TKey key)
    {
        return (int)(object)key;
    }

    private static TKey IndexToKey(int index)
    {
        return (TKey)(object)index;
    }

    public TValue this[int i]
    {
        set { array[i] = value; }
        get { return array[i]; }
    }

    class MyEnumerator : IEnumerator<KeyValuePair<TKey, TValue>>
    {
        private ENumDictionary<TKey, TValue> dictionary;
        private int getIndex;
        private KeyValuePair<TKey, TValue> currentValue;

        public MyEnumerator(ENumDictionary<TKey, TValue> enumDictionary)
        {
            dictionary = enumDictionary;
            getIndex = 0;
        }

        object IEnumerator.Current => currentValue;

        KeyValuePair<TKey, TValue> IEnumerator<KeyValuePair<TKey, TValue>>.Current => currentValue;

        public void Dispose()
        {
        }

        public bool MoveNext()
        {
            if (getIndex >= dictionary.array.Length)
            {
                return false;
            }

            TKey key = IndexToKey(getIndex);
            TValue value = dictionary.array[getIndex];
            currentValue = new KeyValuePair<TKey, TValue>(key, value);
            getIndex++;
            return true;
        }

        public void Reset() { getIndex = 0; }
    }

    public void Add(TKey key, TValue v0)
    {
        array[KeyToIndex(key)] = v0;
    }
}

テストコード

struct StructAB
{
    public int a, b;
    public StructAB(int a, int b)
    {
        this.a = a;
        this.b = b;
    }
    public override string ToString()
    {
        return string.Format("{0},{1}", a, b);
    }
}
    private enum EnumAlpha
    {
        A,
        B,
    }

    void Start()
    {
        ENumDictionary<EnumAlpha, string> dic0 = new ENumDictionary<EnumAlpha, string>()
        {
            {EnumAlpha.A, "A"},
            {EnumAlpha.B, "B"}
        };

        foreach (var it in dic0)
        {
            Debug.Log(" " + it);
        }

        ENumDictionary<EnumAlpha, StructAB> dic1 = new ENumDictionary<EnumAlpha, StructAB>()
        {
            {EnumAlpha.A, new StructAB(12, 13)},
            {EnumAlpha.B, new StructAB(14, 15)}
        };

        foreach (var it in dic1)
        {
            Debug.Log(" " + it.Value);
        }

        Debug.Log("A : " + dic1[EnumAlpha.A]);
        Debug.Log("B : " + dic1[EnumAlpha.B]);

        dic1[EnumAlpha.A] = new StructAB(21, 22);
        Debug.Log("B : " + dic1[EnumAlpha.A]);
    }

private static int KeyToIndex(TKey key)
private static TKey IndexToKey(int index)
以上の enum と int の変換ですが
Expression を駆使すると高速になるようです。
検索すると沢山でてきますよー

初めての投稿です。
間違ってたら教えてください~

0
1
8

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?