web-dev-qa-db-ja.com

C#での辞書デザインの辞書

私の質問:辞書の辞書を作成し、外部/内部キーペアを提供する正規の方法はありますか?実装されたNugetPackageはありますか?

私のコードでは、このようなプロパティがある場所がいくつかあります

private readonly IDictionary<string, IDictionary<string, SomeType>> _nestedDict = 
        new Dictionary<string, IDictionary<string, SomeType>>();

そして、私はこのような拡張メソッドを作成しました

public static V AddOrUpdate<T, U, V>(
    [NotNull] this IDictionary<T, IDictionary<U, V>> dictionary,
    [NotNull] T outerKey,
    [NotNull] U innerKey,
    [NotNull] Func<V> addValueFactory,
    [NotNull] Func<V, V> updateValueFactory,
    [CanBeNull] IEqualityComparer<U> innerDictionaryComparer = null)
{
    IDictionary<U, V> dict;
    if (dictionary.TryGetValue(outerKey, out dict))
    {
        V currentValue;
        if (dict.TryGetValue(innerKey, out currentValue))
        {
            var updatedValue = updateValueFactory(currentValue);
            if (!object.ReferenceEquals(updatedValue, currentValue))
                dict[innerKey] = updatedValue;
            return updatedValue;
        }
        var addedValue1 = addValueFactory();
        dict[innerKey] = addedValue1;
        return addedValue1;
    }

    var addedValue = addValueFactory();
    if (innerDictionaryComparer != null)
        dictionary[outerKey] = new Dictionary<U, V>(innerDictionaryComparer) {{innerKey, addedValue}};
    else
        dictionary[outerKey] = new Dictionary<U, V> {{innerKey, addedValue}};
    return addedValue;
}

これは強力ですが、入れ子になった辞書のクラスを作成する必要があるように感じ始めています。これが私の考えです。

  1. addValueFactoryupdateValueFactoryは不格好で、OOの原則に違反しているように感じます。
  2. ConcurrentDictionarys(またはおそらくDictionarys)のConcurrentDictionaryを作成することを考えていますが、これにはいくつかの拡張メソッドが必要になります。私がそれをこれだけ多く使用しているのであれば、darnクラスを作成してそれで終わらせるべきだと思いました。

何て言うの?

7
Frank Bryce

もっと簡単な方法があるかもしれません。

このことを考慮:

    public class NAryDictionary<TKey, TValue> :
        Dictionary<TKey, TValue>
    {
    }

    public class NAryDictionary<TKey1, TKey2, TValue> :
        Dictionary<TKey1, NAryDictionary<TKey2, TValue>>
    {
    }

    public class NAryDictionary<TKey1, TKey2, TKey3, TValue> :
        Dictionary<TKey1, NAryDictionary<TKey2, TKey3, TValue>>
    {
    }

それからあなたは書くことができます:

    class Program
    {
        static void Main(string[] args)
        {
            var dico3 = new NAryDictionary<bool, int, string, decimal>();

            dico3[false] = new NAryDictionary<int, string, decimal>();
            dico3[false][123] = new NAryDictionary<string, decimal>();
            dico3[false][123]["foo"] = 123456789.012m;

            Console.WriteLine(dico3[false][123]["foo"].ToString("0,0.000"));

            Console.ReadKey();
       }
    }

さて、それはVisual Studioのインテリセンスに対応していますが(上記の割り当てで「=」記号を入力した後の自動コード補完の提案で気付くでしょう)、それは間違いなく、やや面倒です。

... new NAryDictionary<bool, int, string, decimal>()
... new NAryDictionary<int, string, decimal>()

そして

... new NAryDictionary<string, decimal>()

これで軽減できます

    public static class NAryDictionaryExtensions
    {
        public static NAryDictionary<TKey2, TValue> New<TKey1, TKey2, TValue>(this NAryDictionary<TKey1, TKey2, TValue> dictionary)
        {
            return new NAryDictionary<TKey2, TValue>();
        }

        public static NAryDictionary<TKey2, TKey3, TValue> New<TKey1, TKey2, TKey3, TValue>(this NAryDictionary<TKey1, TKey2, TKey3, TValue> dictionary)
        {
            return new NAryDictionary<TKey2, TKey3, TValue>();
        }
    }

より簡単に書けるようになりました

    class Program
    {
        static void Main(string[] args)
        {
            var dico3 = new NAryDictionary<bool, int, string, decimal>();

            dico3[true] = dico3.New();
            dico3[true][456] = dico3[true].New();
            dico3[true][456]["bar"] = 456789012.345m;

            Console.WriteLine(dico3[true][456]["bar"].ToString("0,0.000"));

            Console.ReadKey();
       }
    }

'お役に立てれば。

4
YSharp