If I have an abstract base class called MyBaseClass, and a class deriving from MyBaseClass called MyDerivedClass, is there a way to cast an object that I know is a Dictionary<Guid,MyDerivedClass> to a Dictionary<Guid,MyBaseClass> instead?
I get an invalid cast error when I do:
var dict = (Dictionary<Guid,MyBaseClass>)obj; // Where obj is "object" type but I know is a Dictionary<Guid,MyDerivedClass>.
// This throws an invalid cast error.
The thing that has me confused is that casting an obj that I know is a List<MyDerivedClass> to a List<MyBaseClass> actually works. This works:
var list = (List<MyBaseClass>)obj; // Where obj is "object" type but I know is a List<MyDerivedClass>
// This works
Is there any way to cast an object that is Dictionary<Guid,MyDerivedClass> to Dictionary<Guid,MyBaseClass> without first casting to Dictionary<Guid,MyDerivedClass>? I'd like to avoid have to try casting each derived class if possible.
CodePudding user response:
.NET uses reified generics, so (unlike covariant/contravariant interfaces and arrays) you cannot cast generic classes to have a different signature from what the object actually is. Your example with a List actually doesn't behave the way you say it does:
object obj = new List<MyDerivedClass>();
var list = (List<MyBaseClass>)obj; // invalid cast exception
You can create a new dictionary, though.
var dict = ((Dictionary<Guid, MyDerivedClass>)obj)
.ToDictionary(d => d.Key, d => (MyBaseClass)d.Value);
This will create a copy, and is more expensive than a cast, but for most use cases it won't significantly impact your application's performance.
You could technically create your own class that wraps a differently-typed dictionary and implements an interface like IDictionary<,>
, so you could avoid the up-front cost of creating the dictionary but incur slightly more cost as you use the dictionary.
But, in summary, there is no way to simply cast a generic class to a type that it is not.