Is this a flaw in the vocabulary casting mechanism or, in my opinion, should it be allowed?
In your thinking. You expect dictionaries to be covariant in their transformations. They are not for the following reason. Suppose they were, and deduce what might 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];
The string array is converted to IEnumerable<string>
, but not to List<string>
. You simply put what is not a list of strings in a dictionary that can only accept a list of strings.
In C #, generic types can be covariant or contravariant if all of the following conditions are true:
- You use C # 4 or better.
- A different common type is an interface or delegate.
- Deviation is provably typical. (The C # specification describes the rules we use to determine the safety of variance. The C # 4.0 version of the doc file can be downloaded [here] . See Section 23.5.)
- Type arguments that change are reference types.
- The type has been specifically marked as safe for rejection.
Most of these conditions are not met for the dictionary - it is not an interface or a delegate, it is not safe, and the type is not marked as safe for dispersion. Thus, there is no variance for dictionaries.
IEnumerable<T>
, in contrast, satisfies all of these conditions. You can convert IEnumerable<string>
to IEnumerable<object>
in C # 4.
If the subject of disagreement interests you, consider reading my two dozen articles on this subject:
http://blogs.msdn.com/b/ericlippert/archive/tags/covariance+and+contravariance/
Eric Lippert
source share