In some situations I need to cast down an object to an interface to fit my needs, which implicitly requires to cast down type arguments of generic interfaces.
ICage<TAnimal>
is the interface for a Cage
of an animal of type IAnimal
public interface ICage<TAnimal>
where TAnimal : IAnimal<IOwner>
public class Cage<TAnimal> : ICage<TAnimal>
where TAnimal : IAnimal<IOwner>
public interface IAnimal<out TOwner>
where TOwner : IOwner
IAnimal
needs an Owner of type IOwner
public abstract class Mammal<TOwner> : IAnimal<TOwner>
where TOwner : IOwner
A Mammal is a type of Animal with an Owner of type IOwner
.
public class Human : IOwner
A Human
is a type of IOwner
public class Dog<TOwner> : Mammal<TOwner>
where TOwner : IOwner
A Dog is a type of Mammal.
Now putting everything together:
var cage = new Cage<Mammal<IOwner>>();
var me = new Human()
{
Name = "Hakim"
};
var dog = new Dog<Human>();
dog.Owner = me;
cage.Add((Mammal<IOwner>)dog);
In the last line I get a compile time error CS0030 telling me that I can not convert Dog to Mammel.
This is the same reason why you can't cast a List<string>
to a List<object>
.
Let's say in Mammal
there is a property called Owner
like this:
public TOwner Owner { get; set; }
For an instance of Mammal<IOwner>
, this becomes:
public IOwner Owner { get; set; }
dog
is a Dog<Human>
, which is also a Mammal<Human>
. If you could cast dog
to Mammal<IOwner>
, this would mean that dog.Owner
can suddenly store any type that implements IOwner
. ie this would be possible:
class EvilOwner : IOwner { ... }
Mammal<IOwner> mammal = (Mammal<IOwner>)dog;
mammal.Owner = new EvilOwner();
But that's not possible because dog
at runtime is a Dog<Human>
, which has an Owner
of Human
. EvilOwner
cannot possibly be stored in Human
!
What I suggest you do is to remove the TOwner
generic parameter. If in your mind that Dog<Human>
is also a kind of Mammal<IOwner>
, then it probably makes more sense to design the classes like this:
public interface IAnimal {
IOwner Owner { get; }
}
public abstract class Mammal : IAnimal { ... }
public class Dog : Mammal { ... }
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.