2013-06-26 61 views
5

我试图写的扩展方法,将转换IDictionary<K, S<V>>保持任何类型的收集/序列(S<V>)至ILookup<K, V>这是更适当的数据结构这些情况。这意味着,我想我的分机在不同S类型和接口工作:单的扩展方法<K,IEnumerable的/ IList的/ ICollection的<V>>

  • 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-type参数?

我希望所有上述预期使用量

实例调用成为可能,并导致我的一个扩展方法调用:

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(); 
+0

当你使用它,尽量只指定类型的显式仿制药 – Mgetz

+0

@Mgetz - 我认为这正是NOtherDev试图避免 - 要么指定类型的明确或有假论据来强制类型。预期使用的样本可能会清理一些事情。 –

+0

是的,正如我所提到的,我想要类型推断来完成它的工作。将添加预期的用法示例的问题。 – NOtherDev

回答

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

似乎没有做类型推断的工作方式,但如果你投的字典这种方法将工作:

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

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

0

从测试位我已经做了,这是我的结果。

如果我输入dictOfIEnumerables.ToLookup(,我会看到4个重载方法。
enter image description here

但是,如果我输入dictOfIEnumerables.ToLookup<,我看到所有5重载方法。 enter image description here

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

但是,使用指定的类型确实可以在我的机器上正常工作。 enter image description here

+0

嗯,实际上这个问题不是由于名称冲突造成的,问题依然存在于'ToLookup2'中。我知道我可以明确地指定参数,但这正是我想要避免的。看来我需要去复制每个接口的方法... – NOtherDev

相关问题