Скажем, ваш код скомпилирован. Вы могли бы сделать это:
class Derived : AggregateRoot
{
}
А потом:
var derived = new Derived();
ICopyable copyable = derived;
copyable.Copy<string>("Hello!");
Это было бы хорошо, потому что ICopyable.Copy<T>
требует аргумент типа это класс - и string
класс. Но он должен быть отправлен на метод, который на самом деле ожидает T : AggregateRoot
. Это должно было бы потерпеть неудачу во время выполнения - поэтому компилятор просто отклоняет его заранее.
В более общих чертах проблема заключается в том, что вы пытаетесь реализовать определенный интерфейс с более строгой реализацией, чем то, что говорит интерфейс. Это не безопасно для типа - и это будет нарушать Liskov Substitution Principle в отношении контравариантности входных данных.
Но даже если он был типа safe и не нарушил LSP, он все равно будет отклонен компилятором. C# требует, чтобы специализация класса и реализация интерфейса всегда выполнялись с точными, инвариантными сигнатурами и одинаковыми ограничениями. Это прописано в C# specification, в 13.4.3 Реализации универсальных методов:
When a generic method implicitly implements an interface method, the constraints given for each method type parameter must be equivalent in both declarations [...]
Но все-таки, C# позволяет дисперсию в неявных преобразованиях между родовыми интерфейсами (одного и тем же определением общего типа). Таким образом, ваш код будет работать, если оно было изменено на что-то вроде этого:
public interface ICopyable<in T>
where T : class
{
void Copy(T source);
}
public abstract class AggregateRoot : ICopyable<AggregateRoot>
{
public virtual void Copy(AggregateRoot newAggregateRoot)
{
// my code here.
}
}
И теперь вы можете сделать следующее, который компилирует и типобезопасен:
var derived = new Derived();
ICopyable<AggregateRoot> aggregateCopyable = derived;
ICopyable<Derived> derivedCopyable = aggregateCopyable;
derivedCopyable.Copy(derived);
вы пытались определить Т: класс при определении интерфейса вместо этого? –
Я не знаю, что вы имеете в виду. Прости. –
это было объяснено в ответе ниже :) –