I'm trying to cast an object in a generic object where I need to change the type dynamically.
Dog<T>
inherits Animal
, class " T
" must inherit from EntityBase
. For example, Chihuahua
inherits EntityBase
.
for (int i = 0; i < list.Count(); i++) {
if (list?.ElementAt(i)?.GetType().GetTypeInfo().BaseType == typeof(Animal))
{
var type = list.ElementAt(i).GetType();
// is wrong, must use a class no a type
// var animal = list.ElementAt(i) as GenericObject<Dog<type>>
// Correct syntax but cast results null
var animal = list.ElementAt(i) as GenericObject<Dog<EntityBase>>
// animal is null
DoStuff(animal);
}
If I use this code, it works:
if (list?.ElementAt(i)?.GetType() == typeof(Dog<Chihuahua>))
{
DoStuff(list.ElementAt(i) as Dog<Chihuahua>);
}
I want to do this as generically as possible, thanks a lot!
I will share the project I'm doing when I finish!
The ability to have a single list hold different kinds of related types is called covariance (contravariance is also related). This is achieved in .NET with the out
and in
keywoards respectively. With .NET 4.5, covariance is built into IEnumerable<T>
. IEnumerable<T>
is implemented by IList<T>
, which is implemented by List<T>
.
If you have a list of Animal
s, you can add any subtype of Animal
to the list. However, when you get that animal out, in code, you get a variable of type Animal
that points to your subtype of Animal
. So it looks like you only have an Animal
but it's really the subtype. You could try to manually cast everything as you suggested.
There is another workaround (.NET 4.5), you can use the dynamic
keyword to have the type be determined at runtime. Then overload the DoStuff
method, it should behave the way you want.
public class Animal
{
public string Name;
public Animal() { Name = "Animal"; }
}
public class Dog:Animal
{
public Dog() { Name = "Dog"; }
}
[TestMethod]
public void Test()
{
var list = new List<Animal>();
list.Add(new Dog());
list.Add(new Animal());
foreach(dynamic a in list)
{
DoStuff(a);
}
}
public void DoStuff(Animal animal)
{
Console.WriteLine("{0} is wild", animal.Name);
}
public void DoStuff(Dog dog)
{
Console.WriteLine("{0} is not wild", dog.Name);
}
This is the output
Test Name: Test
Test Outcome: Passed
Result StandardOutput:
Dog is not wild
Animal is wild
Covariance and contravariance is a complex topic. Check out these other posts. Difference between Covariance & Contra-variance Difference between covariance and upcasting
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.