嵌套接口:将IDictionary <TKey,IList >转换为IDictionary <TKey,IEnumerable >?

我认为将IDictionary<TKey, IList>对象转换为IDictionary<TKey, IEnumerable>是相当简单的,但是

 var val = (IDictionary<TKey, IEnumerable>)Value; 

抛出System.InvalidCastException ,和

 var val = Value as IDictionary<TKey, IEnumerable>; 

使val null。 投这个的正确方法是什么?

我认为将IDictionary>对象转换为IDictionary>是相当简单的

绝对不。 它不是类型安全的。 这是一个为什么不这样做的例子:

 // This is fine... IDictionary> dictionary = new Dictionary>(); // Suppose this were valid... IDictionary> badDictionary = dictionary; // LinkedList doesn't implement IList badDictionary["foo"] = new LinkedList(); // What should happen now? IList bang = dictionary["foo"]; 

正如您所看到的,这将导致问题 – 当我们期望所有值实现IList时,我们将尝试获取LinkedList IList 。 generics的要点是类型安全 – 那么你预计哪一行会失败? 第一行,第三行和第四行对我来说看起来非常有效 – 所以第二行是唯一一个无法编译的行,它确实……

现在在某些情况下,它可以安全地完成。 例如,您可以将(在C#4中)从IEnumerableIEnumerable因为IEnumerable仅在“输出”位置使用T

有关详细信息,请参阅MSDN 。

编辑:只是为了澄清 – 使用现有键/值对的副本创建一个词典很容易,例如使用链接:

 var copy = original.ToDictionary>(pair => pair.Key, pair => pair.Value); 

您只需要知道您现在有两个单独的词典。

这可能会或可能不会帮助你,但我想我会把它作为Jon的回答的补充。

如果你需要的只是字典的 ,而不参考它们的键,你可以这样做:

 IDictionary> dictionary = Whatever(); var values = (IEnumerable>)dictionary.Values; 

为此,您必须使用C#4.0或更高版本,并且必须将TValue约束为引用类型。 这是代码,稍加重构,并附有注释来解释:

 IDictionary> dictionary = Whatever(); //Values returns an ICollection> ICollection> temp1 = dictionary.Values; //ICollection inherits from IEnumerable IEnumerable> temp2 = temp1; //IEnumerable is covariant //There is an implicit reference conversion between IList and IEnumerable //So there is an implicit reference conversion between IEnumerable> //and IEnumerable> IEnumerable> values = temp2;