嵌套接口:Cast IDictionary> to IDictionary
本文关键字:IDictionary TValue TK to IList TKey 接口 Cast 嵌套 | 更新日期: 2023-09-27 18:32:45
我认为将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
为空。 正确的投射方法是什么?
我认为将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"];
如您所见,这会导致问题 - 当我们期望所有值都实现IList<int>
时,我们会尝试LinkedList<int>
出来。泛型的要点是类型安全的 - 那么你预计哪一行会失败?第一、第三和第四行对我来说很明显有效——所以第二行是唯一无法编译的行,而且确实......
现在在某些情况下,它可以安全地完成。例如,可以将(在 C# 4 中(从 IEnumerable<string>
转换为IEnumerable<object>
IEnumerable<T>
因为仅在"输出"位置使用T
。
有关更多详细信息,请参阅 MSDN
。编辑:只是为了澄清 - 很容易创建一个带有现有键/值对副本的新字典,例如使用链接:
var copy = original.ToDictionary<TKey, IEnumerable<TValue>>(pair => pair.Key,
pair => pair.Value);
您只需要知道您现在有两个单独的词典。
这可能会也可能不会帮助你,但我想我会把它作为乔恩答案的补充。
如果您只需要字典的值,而不引用它们的键,则可以执行以下操作:
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;
本文关键字:IDictionary TValue TK to IList TKey 接口 Cast 嵌套 | 更新日期: 2023-09-27 18:32:45
我认为将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
为空。 正确的投射方法是什么?
我认为将
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"];
如您所见,这会导致问题 - 当我们期望所有值都实现IList<int>
时,我们会尝试LinkedList<int>
出来。泛型的要点是类型安全的 - 那么你预计哪一行会失败?第一、第三和第四行对我来说很明显有效——所以第二行是唯一无法编译的行,而且确实......
现在在某些情况下,它可以安全地完成。例如,可以将(在 C# 4 中(从 IEnumerable<string>
转换为IEnumerable<object>
IEnumerable<T>
因为仅在"输出"位置使用T
。
有关更多详细信息,请参阅 MSDN
。编辑:只是为了澄清 - 很容易创建一个带有现有键/值对副本的新字典,例如使用链接:
var copy = original.ToDictionary<TKey, IEnumerable<TValue>>(pair => pair.Key,
pair => pair.Value);
您只需要知道您现在有两个单独的词典。
这可能会也可能不会帮助你,但我想我会把它作为乔恩答案的补充。
如果您只需要字典的值,而不引用它们的键,则可以执行以下操作:
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;