Dizionario dei dizionari design in C #

5

La mia domanda: c'è un modo canonico per creare un dizionario di dizionari e fornire una coppia di chiavi esterna / interna? Esiste un NugetPackage con un'implementazione?

Nel mio codice, ho ora alcuni luoghi in cui ho una proprietà come questa

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

e ho creato metodi di estensione come questo

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;
}

Questo è potente, ma sto iniziando a sentire che dovrei semplicemente creare una classe per i dizionari nidificati. Ecco il mio pensiero:

  1. Il addValueFactory e updateValueFactory sono un po 'maldestri e sembra che stiano rompendo i principi OO.
  2. Sto pensando di creare un ConcurrentDictionary di Dictionary s (o forse di ConcurrentDictionary s), e questo richiederebbe un maggior numero di metodi di estensione. Ho pensato che se lo sto usando così tanto, dovrei solo creare la classe darn e farla finita.

Che cosa dici?

    
posta Frank Bryce 23.05.2016 - 16:50
fonte

1 risposta

3

Potrebbe esserci un modo più semplice verso di esso.

Considera questo:

    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>>
    {
    }

Quindi puoi scrivere:

    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();
       }
    }

Ora, sebbene sia intuitivo per Visual Studio (come noterai con le proposte di completamento automatico del codice dopo aver digitato i segni "=" negli incarichi precedenti), è discutibilmente un po 'macchinoso, tuttavia, a causa di quelli

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

e

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

Che può essere alleviato con

    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>();
        }
    }

permettendo ora di scrivere, più semplicemente,

    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();
       }
    }

'Spero che questo aiuti.

    
risposta data 07.10.2016 - 22:09
fonte

Leggi altre domande sui tag