Метод одиночного расширения для IDictionary<K, IEnumerable / IList / ICollection <V >>
Я пытаюсь написать метод расширения, который будет конвертировать IDictionary<K, S<V>>
проведение любого типа коллекции / последовательности (S<V>
) чтобы ILookup<K, V>
которая является более правильной структурой данных в этих случаях. Это означает, что я хотел бы, чтобы мое расширение работало на разных S
типы и интерфейсы:
IDictionary<K, IEnumerable<V>>
IDictionary<K, ICollection<V>>
IDictionary<K, List<V>>
и т.д. В идеале я не хочу писать отдельную реализацию для каждого возможного типа коллекции И я хочу, чтобы вывод типа выполнял свою работу.
Что я пробовал это:
public static ILookup<TKey, TValue>ToLookup<TKey, TCollection, TValue>(
this IDictionary<TKey, TCollection> dictionary)
where TCollection : IEnumerable<TValue>
Но это не имеет TValue
в списке параметров, поэтому вывод типа не может понять это - я получаю "Аргументы типа для метода ToLookup не могут быть выведены из использования".
Есть ли шанс, что это может работать как-то иначе, чем добавление подделки TValue
параметр для метода?
Примеры ожидаемого использования
Я надеюсь, что все вышеперечисленные вызовы будут возможны и приведут к вызову моего единственного метода расширения:
var dictOfIEnumerables = new Dictionary<int, IEnumerable<int>>();
var lookupFromIEnumerables = dictOfIEnumerables.ToLookup();
var dictOfICollections = new Dictionary<int, ICollection<int>>();
var lookupFromICollections = dictOfICollections.ToLookup();
var dictOfLists = new Dictionary<int, List<int>>();
var lookupFromLists = dictOfLists.ToLookup();
2 ответа
Потому что все коллекции реализуют IEnumerable<T>
мы можем просто использовать его вместо TCollection
Тип параметра. К сожалению, вывод типа не знает этого. Это код, который я написал:
public static ILookup<TKey, TValue> ToLookup<TKey, TValue>
(this IDictionary<TKey, IEnumerable<TValue>> dict)
{
return dict.SelectMany(p => p.Value.Select
(v => new KeyValuePair<TKey, TValue>(p.Key, v)))
.ToLookup(p => p.Key, p => p.Value);
}
Кажется, нет никакого способа заставить вывод типа работать, но этот метод будет работать, если вы приведете словарь:
((IDictionary<int, IEnumerable<int>>)dictOfLists).ToLookup()
Также вы можете добавлять списки в словарь IEnumerables и отбрасывать их обратно, когда они вам нужны.
После небольшого тестирования, которое я сделал, вот мои результаты.
Если я наберу dictOfIEnumerables.ToLookup(
Вижу 4 перегруженных метода.
Однако, если я наберу dictOfIEnumerables.ToLookup<
Вижу все 5 перегруженных методов.
Похоже, что вывод типа не работает из-за конфликта имен / разрешения между ToLookup(), который определен в IEnumerable. По-видимому, без угловых скобок это разрешает методы, определенные в IEnumerable, потому что это то, чем ограничивается TCollection. Может быть, кто-то в Stackru, который умнее меня, может объяснить вам, почему он работает так, как работает.
Тем не менее, использование указанных типов, на самом деле, работает правильно на моем компьютере.