Однако мне интересно, почему мне нужно разыграть, когда у меня есть где I : IAnimal
.
Да, вы гарантировали, что I
будет подклассом IAnimal
или IAnimal
, но что вернет Construct
? Construct
может вернуть другой подкласс от I
.
Всякий раз, когда вы используете обобщенные типы, вы должны помнить, что универсальные типы параметров предоставляются клиентским кодом вашего класса / метода, а не классом / методом. Здесь вы заставляете I
быть Dog
, используя DogConstructor
, если не были переданы аргументы. Если вы делаете это, то это, вероятно, означает, что генерики здесь не подходят. Попробуйте удалить его:
public class Operation
{
public Operation() : this(new DogConstructor())
{ }
public Operation(IConstructor constructor)
{
IAnimal animal = constructor.Construct("myDog");
}
}
Теперь, если вы настаиваете на использовании дженериков, вы не можете просто предположить, что DogConstructor
по умолчанию, и IConstructor
, вероятно, должно быть также и дженериком:
public interface IConstructor<T> where I: IAnimal
{
T Construct(string name);
}
public class DogConstructor : IConstructor<Dog>
{
Dog Construct(string name)
{
return new Dog(name);
}
}
public class Operation<I> where I : IAnimal
{
public Operation(IConstructor<I> constructor)
{
I animal = constructor.Construct("myDog");
}
}
public class DogOperation: Operation<Dog> {
public DogOperation() : base(new DogConstructor()) {}
}
, поскольку класс Dog не имеет конструктора без параметров
Другое решение может заключаться в том, чтобы ограничить I
так, чтобы он имел конструктор без параметров, и добавить его в Dog
:
class Operation<I> where I : IAnimal, new() {