Странное использование дженериков

После небольшого программирования один из моих классов использовал дженерики таким образом, которого я никогда раньше не видел. Мне хотелось бы получить некоторые мнения об этом, если это плохое кодирование или нет.

abstract class Base<T> : where T : Base<T>
{
    // omitted methods and properties.
    virtual void CopyTo(T instance) { /*code*/ }
}

class Derived : Base<Derived>
{
    override void CopyTo(Derived instance)
    { 
         base.CopyTo(instance);
         // copy remaining stuff here
    }
}

Это ОК использование дженериков или нет? Я в основном думаю об ограничении на "себя". Иногда мне кажется, что дженерики могут "взорваться" в других классах, где я использую базовый класс.

Ответы

Ответ 1

Да, это разумно - у меня что-то похожее в моем порту протокольных буферов (кроме более сложных, так как есть два взаимно связанных типа).

Вы абсолютно правы в том, что генерические средства иногда заканчиваются распространением по кодовой базе - то, что вы здесь сделали, означает, что бит кода, который заботится только о Derived, имеющий соответствующий API, не должен беспокоиться о том, дженерики.

Мой совет - стараться держать его простым, где это возможно, но в тех случаях, когда "странное" ограничение общего характера действительно описывает то, что вы хотите, идите на это. Вы должны знать, что это не приводит к действительным действиям, но вы можете легко:

class Banana : Base<Derived>

и это будет действительным, хотя и нечетным и, вероятно, неожиданным для пользователей.

Возможно, вы также захотите рассмотреть вопрос о герметизации Derived здесь - если вы выйдете дальше, вы, скорее всего, закончите нечетное поведение (или, по крайней мере, нечетный API).