c # универсальный метод слияния для словарей и упорядоченных словарей - PullRequest
0 голосов
/ 15 сентября 2018

Я создаю следующий вспомогательный метод для объединения словарей (перезаписывая повторяющиеся значения):

public static IDictionary<T1, T2> Merge<T1, T2>(
    IDictionary<T1, T2> source, IDictionary<T1, T2> additional
) {
    var result = new Dictionary<T1, T2>(source);
    additional.ToList().ForEach(pair => result[pair.Key] = pair.Value);
    return result;
}

Я бы хотел сделать его общим, чтобы:

  • Я могу использовать его с OrderedDictionary
  • Возвращает словарь того же типа, что и источник

Есть идеи, как этого добиться или как-то улучшить мою функцию?

1 Ответ

0 голосов
/ 15 сентября 2018

Я могу придумать несколько способов (ни один из них не очень хорош)

1) Если вы не возражаете против изменения исходного словаря, просто добавьте к нему и верните его вместо создания нового словаря

2) Если вызывающий знает конкретный тип словаря, вы можете явно вызвать универсальный метод и сообщить ему, какой тип возвращать или:

3) Вы можете использовать универсальный класс для конкретного типа

4) Вместо непосредственного использования классов словаря, производных от них и сделайте их ICloneable.Затем используйте клон вместо нового словаря

РЕДАКТИРОВАТЬ:

Для варианта # 2, я обнаружил, что вам не нужны явные вызовы общего характера, достаточно явных приведений,Вы могли бы иметь такой код:

namespace ConsoleApp1
{
    class Program
    {
        public static T Merge<T>( T source, IDictionary additional) where T:IDictionary,new()
        {
            var result = new T();
            foreach (var item in additional.Keys)
            {
                result.Add(item, additional[item]);
            }
            foreach (var item in source.Keys)
            {
                result.Add(item, source[item]);
            }
            return result;
        }

        static void Main(string[] args)
        {
            OrderedDictionary od = new OrderedDictionary();
            od["A"] = 1;

            System.Collections.Generic.Dictionary<String, Int32> dictionary = new System.Collections.Generic.Dictionary<String, Int32>();
            dictionary["B"] = 2;
            IDictionary od2 = Merge(od, dictionary);
            Console.WriteLine("output=" + od2["A"]+od2["B"]+od2.GetType());
            IDictionary dictionary2 = Merge(dictionary, od);
            Console.WriteLine("output=" + dictionary2["A"] + dictionary2["B"] + dictionary2.GetType());
            Console.ReadKey();
        }
    }
}

Вот некоторые примечания:

1) Вы должны использовать неуниверсальный System.Collections.IDictionary в качестве типа параметра.Это общий для Dictionary и OrderedDictionary, потому что OrderedDictionary не является универсальным типом

2) Чтобы создать новый для T и заставить его быть только IDictionaries, вы должны добавить предложение where

3) Если у вас нет переменных для двух входных данных, объявленных как конкретные типы, а есть только их интерфейсы, все становится ужасно, и тогда вам нужно явное приведение (показано ниже).В этом случае может быть лучше выбрать опцию # 5 и просто дать вызывающей стороне передать целевой контейнер, который они хотели бы, в качестве третьего параметра

    IDictionary od = new OrderedDictionary();
    od["A"] = 1;
    System.Collections.Generic.IDictionary<String, Int32> dictionary = new System.Collections.Generic.Dictionary<String, Int32>();
    dictionary["B"] = 2;
    IDictionary od2 = Merge((OrderedDictionary)od, (System.Collections.Generic.Dictionary<String, Int32>) dictionary);
    Console.WriteLine("output=" + od2["A"]+od2["B"]+od2.GetType());
    IDictionary dictionary2 = Merge((System.Collections.Generic.Dictionary<String, Int32>)dictionary, od);
    Console.WriteLine("output=" + dictionary2["A"] + dictionary2["B"] + dictionary2.GetType());
    Console.ReadKey();
...