[英]C# type conversion: Explicit cast exists but throws a conversion error?
我了解到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):
无法隐式转换类型
System.Collections.Generic.IDictionary<T, System.Collections.Generic.HashSet<T>>
toSystem.Collections.Generic.IDictionary<T, System.Collections.Generic.IEnumerable<T>>
。存在显式转换(您是否错过了演员?)
但如果我通过写作进行演员表演
IDictionary<T, IEnumerable<T>> bar2 = (IDictionary<T, IEnumerable<T>>) bar;
然后我在运行时获得了无效的强制转换异常。
两个问题:
HashSet
确实实现了IEnumerable
接口? 它不起作用的原因是IDictionary<TKey, TValue>
值不是共变体 (并且也是关键,出于同样的原因)。 如果允许,则此代码将编译,但必须导致异常:
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());
我该如何解决这个问题? 是迭代密钥并逐步建立新字典的唯一方法吗?
它可能不是最优雅的解决方案,但它有效:
IDictionary<T, HashSet<T>> bar = new Dictionary<T, HashSet<T>>();
IDictionary<T, IEnumerable<T>> bar2 = bar.ToDictionary(x => x.Key, y => (IEnumerable<T>)y.Value);
Dictionary强制转换不起作用的原因是因为IEnumerable
是共变量,请注意声明中的<out T>
public interface IEnumerable<out T> : IEnumerable
IDictionary
不是。
public interface IDictionary<TKey, TValue> : ICollection<KeyValuePair<TKey, TValue>>, IEnumerable<KeyValuePair<TKey, TValue>>, IEnumerable
你可以在这里阅读更多相关信息: https : //msdn.microsoft.com/en-us/library/dd799517(v = vs1010).aspx
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.