If I try and do:
IDictionary<uint, IEnumerable<string>> dict = new Dictionary<uint, List<string>>();
I get the error:
error CS0266: Cannot implicitly convert type
‘System.Collections.Generic.Dictionary>’
to
‘System.Collections.Generic.IDictionary>’.
An explicit conversion exists (are you missing a cast?)
If I add the cast:
IDictionary<uint, IEnumerable<string>> dict = (IDictionary<uint, IEnumerable<string>>)new Dictionary<uint, List<string>>();
Then it compiles.
Why do I need the explicit cast? And is it safe? I thought the whole point on covariance was the ability to implicitly cast safely?
EDIT:
C# prevents unrelated casting eg
string s = (string)0L;
error CS0030: Cannot convert type ‘long’ to ‘string’
It does allow explicit downcasting of related types when you know that the object is actually a subclass:
Animal animal = new Cat();
Cat cat = (Cat)animal;
I am confused why the compiler is offering, and allowing me to explicitly cast to an IDictionary with incompatible types.
It is not safe. For example, you could now write
dict.Add(5, new string[0]), which would blow up, since astring[]is not aList<string>. The fact that it is unsafe is why you need the cast.Edit to address your updated concern:
C# allows any explicit cast from any reference type S to any interface T (“provided S is not sealed and provided S does not implement T.”) This behavior is specified in section 6.2.4 of the language spec. So this is legal:
I can’t say why this is the case, other than the fact that the C# type system was originally even more constrained than it is today (e.g. no generics, no variance) so I’m sure that there were a lot of cases in which being able to hack around it with casts was very convenient.