Для этого вам нужно будет коварианты (или это контравариантные) параметры. К сожалению, их можно указывать только на интерфейсах или делегатах, а не на классах. Один из способов получить то, что вы хотите, будет создавать интерфейс на вершине класса Vet, следующим образом:
// Not sure what you need this enum for, but OK...
enum AnimalType {dog, cat}
class Animal{}
class Dog : Animal {}
class Cat : Animal {}
// Create an interface with covariant parameter
// i.e. an IVet<T> is also an IVet<Animal> for all T deriving from Animal.
interface IVet<out T> where T : Animal {}
// Made Vet abstract. You can still use this to provide base implementations for concrete Vets.
abstract class Vet<T> : IVet<T> where T : Animal {}
class DogVet : Vet<Dog> {}
class CatVet : Vet<Cat> {}
static void Main()
{
// Must use the interface here.
IVet<Animal> vet = new DogVet();
}
Чтобы быть честным, хотя, код вы вывесили заставляет меня задаться вопросом, если проблема не с дизайном вашего кода, а не синтаксиса.
Обратите внимание, что хотя это скомпилировано, предупреждение от ответа Стенли действительно. Например, вы не можете добавить метод void Treat(T patient)
к интерфейсу, например.
Момент, когда вы оказываетесь проверки типов во время выполнения, или получать ошибки компиляции, потому что ваш базовый класс определяет функцию, принимая T
в качестве параметра, и он не будет принимать реализацию с Dog
в производном классе, вы должны перепроектировать вашей программы. На самом деле, я бы серьезно подумал об этом прямо сейчас.
Код запах здесь, что у вас есть дерево наследования на Animal
, которое вы имитируете другим деревом наследования Vet
. Невозможность добавить правильный производный Vet
для нового производного Animal
даст вам головные боли.
Btw, вы написание AnimalType как «AnymalType» в своем объявлении словаря – WhiteRuski