5

我正在尝试编写一个扩展方法,它将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除了在方法中添加 fake -typed 参数之外,它是否有可能以其他方式工作?

预期用法示例

我希望上述所有调用都是可能的,并导致调用我的单个扩展方法:

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

2 回答 2

1

因为所有的集合都实现了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);
}

似乎没有办法使类型推断起作用,但是如果您转换 Dictionary,此方法将起作用:

((IDictionary<int, IEnumerable<int>>)dictOfLists).ToLookup()

您还可以将列表添加到 IEnumerables 字典中,并在需要时将它们转换回来。

于 2013-09-19T17:19:56.333 回答
0

从我所做的一些测试来看,这是我的结果。

如果我键入dictOfIEnumerables.ToLookup(,我会看到 4 个重载方法。
在此处输入图像描述

但是,如果我键入dictOfIEnumerables.ToLookup<,我会看到所有 5 个重载方法。 在此处输入图像描述

由于在 IEnumerable 上定义的 ToLookup() 之间的名称冲突/分辨率冲突,类型推断似乎不起作用。显然,没有尖括号,它解析为 IEnumerable 上定义的方法,因为这是 TCollection 的限制。也许 StackOverflow 上的某个人比我更聪明的人可以向您解释为什么它会以这种方式工作。

但是,实际上,使用指定的类型确实可以在我的机器上正常工作。 在此处输入图像描述

于 2013-07-01T21:50:21.773 回答