abstract class Animal { }
class Mammal : Animal { }
class Dog : Mammal { }
class Reptile : Animal { }
class AnimalWrapper<T> where T : Animal
{
public ISet<AnimalWrapper<T>> Children { get; set; }
}
class Program
{
public static void Main(string[] args)
{
var foo = new AnimalWrapper<Mammal>();
foo.Children = new HashSet<AnimalWrapper<Mammal>>();
var child = new AnimalWrapper<Dog>();
foo.Children.Add(child);
}
}
这显然不能编译,因为foo.Children.Add(child);
我不确定上面的代码是否是演示我想要做的最清晰的方式,所以我将尝试用简单的英语解释:
我希望能够拥有一个类,其子对象属于ISet
相同的泛型类型。因此,如果我也有var child = new AnimalWrapper<Reptile>();
它,在编译时会foo.Children.Add(child);
因为Reptile
is not 也不会继承自Mammal
. 但是,显然,即使它是派生的,如上所示,它也不起作用。
最终,能够说ISet<AnimalWrapper<Animal>> baz = new HashSet<AnimalWrapper<Animal>>();
然后将 a 添加new AnimalWrapper<Mammal>()
到该集合以及new AnimalWrapper<Reptile>()
同一集合中会很好。如上所述,他们的孩子将拥有一个属于自己类型的财产Children
。ISet<AnimalWrapper<T>>
有什么办法,还是我对 C# 期望过高?哎呀,我自己都糊涂了。:)
编辑:好的,所以我几乎想通了,没有AnimalWrapper
,但有一个基本IAnimal
接口,它几乎可以工作:
interface IAnimal { }
abstract class Animal<T> : IAnimal where T : Animal<T>
{
public ISet<T> Children { get; set; }
}
class Mammal : Animal<Mammal> { }
class Dog : Mammal { }
class Reptile : Animal<Reptile> { }
class Frog : Reptile { }
class Program
{
public static void Main(string[] args)
{
var animals = new HashSet<IAnimal>(); // any animal can be in this
var mammal = new Mammal();
animals.Add(mammal);
mammal.Children = new HashSet<Mammal>();
var dog = new Dog();
mammal.Children.Add(dog); // ok! a dog is a mammal
dog.Children = new HashSet<Dog>(); // in theory, OK, but compile time error
// because Dog : Mammal, and Mammal defines Animal<Mammal>, therefore Dog's
// Children is actually ISet<Mammal>, rather than ISet<Dog> (which is what
// I want, recursively apply the T in Animal.
Mammal mammal2 = new Mammal();
dog.Children.Add(mammal2); // should be verboten, but is allowed for the
// same reason above.
}
}