我了解到HashSet
实现 IEnumerable
界面。因此,可以隐式地转换一个 HashSet
。对象进入 IEnumerable
:
HashSet<T> foo = new HashSet<T>();
IEnumerable<T> foo2 = foo; // Implicit cast, everything fine.
这也适用于嵌套的泛型类型:
HashSet<HashSet<T>> dong = new HashSet<HashSet<T>>();
IEnumerable<IEnumerable<T>> dong2 = dong; // Implicit cast, everything fine.
至少我是这么想的。但是如果我做一个Dictionary
,我遇到了一个问题:
IDictionary<T, HashSet<T>> bar = new Dictionary<T, HashSet<T>>();
IDictionary<T, IEnumerable<T>> bar2 = bar; // compile error
最后一行给出了以下编译错误(Visual Studio 2015):
Cannot implicitly convert type
System.Collections.Generic.IDictionary<T, System.Collections.Generic.HashSet<T>>
toSystem.Collections.Generic.IDictionary<T, System.Collections.Generic.IEnumerable<T>>
.An explicit conversion exists (are you missing a cast?)
但是如果我通过写作来进行转换
IDictionary<T, IEnumerable<T>> bar2 = (IDictionary<T, IEnumerable<T>>) bar;
然后我在运行时得到一个无效的转换异常。
两个问题:
- 我该如何解决这个问题?迭代键并一点一点地构建新字典是唯一的方法吗?
- 为什么我首先遇到这个问题,即使
HashSet
确实实现了IEnumerable
界面?
最佳答案
它不起作用的原因是 IDictionary<TKey, TValue>
中的值不是 co-variant (出于同样的原因,也不是关键)。如果允许的话,那么这段代码可以编译,但必须导致异常:
IDictionary<T, HashSet<T>> foo = new Dictionary<T, HashSet<T>>();
IDictionary<T, IEnumerable<T>> bar = foo;
foo.Add(key, new List<T>());
你会想添加一个 List<T>
会起作用,因为它会编译,因为值类型应该是 IEnumerable<T>
.但是,它不会成功,因为实际 值类型是 HashSet<T>
.
所以,是的:唯一的方法是创建一个新字典。
var bar = foo.ToDictionary(x => x.Key, x => x.Value.AsEnumerable());
关于C#类型转换: Explicit cast exists but throws a conversion error?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38503311/