为什么我不能投一个值类型的字典到另一个值类型的字典时的值类型可以相互定投? [英] Why can't I cast a dictionary of one value type to dictionary of another value type when the value types can be cast from one another?
问题描述
可能重复:结果
的在C#中,为什么不能一名单<串GT;对象被存储在一个列表与所述;对象>可变
块引用>
为什么没有下文的工作?
列表<串GT; castMe =新的List<串GT;();
IEnumerable的<串GT; getFromCast =(IEnumerable的<串GT;)castMe; //允许的。
&字典LT; INT,列表与LT;串GT;> castMeDict =新词典< INT,列表与LT;串GT;>();
&字典LT; INT,IEnumerable的<串GT;> getFromDict =(词典< INT,IEnumerable的<串GT;>)castMeDict; //不允许
这是在
词典缺陷
铸造机制,或者在我的思想,这应该被允许?
感谢。
解决方案
这是字典中铸造机制的缺陷,或在我的思想,这应该被允许?
块引用>
在你的思维。你期望的字典应的协的在他们的转换。它们都没有,由于以下原因。假设他们,并推断这可能出问题:
词典< INT,列表与LT;串>> castMeDict =
新字典< INT,列表与LT;串GT;>();
&字典LT; INT,IEnumerable的<串GT;> getFromDict =
(词典< INT,IEnumerable的<串GT;>)castMeDict;
castMeDict [123] =新的List<串GT;();
IEnumerable的<串GT;串= getFromDict [123]; // 没问题!
getFromDict [123] =新的String [] {你好}; // 大问题!
字符串数组可以转换为
的IEnumerable<串>
而不是列表<串GT;
。你只要把东西是的不的字符串转换成字典,只能采取字符串列表清单。
在C#泛型类型可能是协变或逆变如果满足下列所有条件都满足:
- 您正在使用C#4或更好
- 的不同泛型类型是一个接口或委托。
- 的变化可证明是类型安全的。 (C#的规范描述,我们用它来确定方差的安全规则。C#4.0版本doc文件可以下载的 [这里] 。见23.5。)
- 的类型参数的变化都是引用类型。
- 类型已专门标记为方差安全
大多数这些条件没有得到满足的字典 - 它不是接口或委托,它不是可证明安全的,并且类型未标记为方差为安全的。所以,没有方差字典
的IEnumerable< T>
相比之下并不满足所有这些条件。您可以将的IEnumerable<串>
到的IEnumerable<对象>
在C#4
如果方差的主题感兴趣,可以阅读我的二十几文章的主题:
的 http://blogs.msdn.com/b/ericlippert/archive/tags/covariance+and+contravariance/
Possible Duplicate:
In C#, why can't a List<string> object be stored in a List<object> variableWhy doesn't the below work?
List<string> castMe = new List<string>(); IEnumerable<string> getFromCast = (IEnumerable<string>)castMe; // allowed. Dictionary<int, List<string>> castMeDict = new Dictionary<int, List<string>>(); Dictionary<int, IEnumerable<string>> getFromDict = (Dictionary<int, IEnumerable<string>>)castMeDict; // Not allowed
Is this a flaw in the
Dictionary
casting mechanism, or in my thinking that this should be allowed?Thanks.
解决方案Is this a flaw in the Dictionary casting mechanism, or in my thinking that this should be allowed?
In your thinking. You are expecting that dictionaries should be covariant in their conversions. They are not, for the following reason. Suppose they were, and deduce what could go wrong:
Dictionary<int, List<string>> castMeDict = new Dictionary<int, List<string>>(); Dictionary<int, IEnumerable<string>> getFromDict = (Dictionary<int, IEnumerable<string>>)castMeDict; castMeDict[123] = new List<string>(); IEnumerable<string> strings = getFromDict[123]; // No problem! getFromDict[123] = new string[] { "hello" }; // Big problem!
An array of string is convertible to
IEnumerable<string>
but not toList<string>
. You just put something that is not a list of string into a dictionary that can only take list of string.In C# generic types may be covariant or contravariant if all the following conditions are met:
- You're using C# 4 or better.
- The varying generic type is an interface or delegate.
- The variance is provably typesafe. (The C# specification describes the rules we use to determine variance safety. C# 4.0 Version doc file can be downloaded [here]. See section 23.5.)
- The type arguments that vary are all reference types.
- The type has been specifically marked as safe for variance.
Most of those conditions are not met for dictionary -- it is not an interface or delegate, it is not provably safe, and the type is not marked as safe for variance. So, no variance for dictionaries.
IEnumerable<T>
by contrast does meet all those conditions. You can convertIEnumerable<string>
toIEnumerable<object>
in C# 4.If the subject of variance interests you, consider reading my two dozen articles on the subject:
http://blogs.msdn.com/b/ericlippert/archive/tags/covariance+and+contravariance/
这篇关于为什么我不能投一个值类型的字典到另一个值类型的字典时的值类型可以相互定投?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!