我认为将IDictionary<TKey, IList<TValue>>
对象转换为IDictionary<TKey, IEnumerable<TValue>>
是相当简单的,但
var val = (IDictionary<TKey, IEnumerable<TValue>>)Value;
抛出System.InvalidCastException
和
var val = Value as IDictionary<TKey, IEnumerable<TValue>>;
使val
为空。投这个的正确方法是什么?
答案 0 :(得分:7)
我认为将
是相当简单的IDictionary<TKey, IList<TValue>>
对象转换为IDictionary<TKey, IEnumerable<TValue>>
绝对不是。它不是类型安全的。以下是为什么不这样做的例子:
// This is fine...
IDictionary<string, IList<int>> dictionary = new Dictionary<string, IList<int>>();
// Suppose this were valid...
IDictionary<string, IEnumerable<int>> badDictionary = dictionary;
// LinkedList<T> doesn't implement IList<T>
badDictionary["foo"] = new LinkedList<int>();
// What should happen now?
IList<int> bang = dictionary["foo"];
正如您所看到的,这会导致问题 - 当我们期望所有值都实现LinkedList<int>
时,我们会尝试获取IList<int>
。泛型的要点是类型安全 - 那么你期望失败的那条线?第一行,第三行和第四行对我来说看起来非常有效 - 所以第二行是 only 一行无法编译,而且确实...
现在在一些案例中,可以安全地完成。例如,您可以将(在C#4中)从IEnumerable<string>
转换为IEnumerable<object>
,因为IEnumerable<T>
仅在“输出”位置使用T
。
有关详细信息,请参阅MSDN。
编辑:只是为了澄清 - 使用现有键/值对的副本创建新字典很容易,例如:使用链接:
var copy = original.ToDictionary<TKey, IEnumerable<TValue>>(pair => pair.Key,
pair => pair.Value);
您只需要知道您现在有两个单独的词典。
答案 1 :(得分:0)
这可能会或可能不会帮助你,但我认为我会把它作为Jon答案的补充。
如果你需要的只是字典的值,而不参考它们的键,你可以这样做:
IDictionary<TKey, IList<TValue>> dictionary = Whatever();
var values = (IEnumerable<IEnumerable<TValue>>)dictionary.Values;
要使其正常工作,您必须使用C#4.0或更高版本,并且必须将TValue限制为引用类型。这是代码,稍加重构,并附有注释来解释:
IDictionary<TKey, IList<TValue>> dictionary = Whatever();
//Values returns an ICollection<IList<TValue>>
ICollection<IList<TValue>> temp1 = dictionary.Values;
//ICollection<T> inherits from IEnumerable<T>
IEnumerable<IList<TValue>> temp2 = temp1;
//IEnumerable<T> is covariant
//There is an implicit reference conversion between IList<T> and IEnumerable<T>
//So there is an implicit reference conversion between IEnumerable<IList<T>>
//and IEnumerable<IEnumerable<T>>
IEnumerable<IEnumerable<TValue>> values = temp2;