Ограничения параметров рефлексивного типа: X , где T: X - какие-нибудь более простые альтернативы?

Время от времени я усложняю простой интерфейс, добавляя к нему ограничение параметра самореферентного ("рефлексивного") типа. Например, я мог бы превратить это:

interface ICloneable
{
    ICloneable Clone();
}

class Sheep : ICloneable
{
    ICloneable Clone() { … }
} //^^^^^^^^^^

Sheep dolly = new Sheep().Clone() as Sheep;
                                //^^^^^^^^

в:

interface ICloneable where TImpl : ICloneable
{
    TImpl Clone();
}

class Sheep : ICloneable
{
    Sheep Clone() { … }
} //^^^^^

Sheep dolly = new Sheep().Clone();

Основное преимущество: реализуемый тип (например, Sheep ) теперь может ссылаться на себя, а не на базовый тип, что снижает потребность в типах. приведение (как показано в последней строке кода).

Хотя это очень хорошо, я также заметил, что эти ограничения параметров типа не интуитивно понятны и имеют тенденцию становиться действительно трудными для понимания в более сложных сценариях. *)

Вопрос: Кто-нибудь знает другой шаблон кода C #, который дает такой же эффект или что-то подобное, но более легким для понимания образом?


*) Этот код шаблон может быть неинтуитивным и трудным для понимания, например следующими способами:

  • Объявление X , где T: X кажется рекурсивным, и можно задаться вопросом, почему компилятор не застревает в бесконечном цикле , рассуждение, «Если T является X , то X действительно X … >> . " (Но очевидно, что ограничения таким образом не разрешаются.)

  • Для разработчиков может быть неочевидно, какой тип следует указать вместо TImpl . (Ограничение в конечном итоге позаботится об этом.)

  • Как только вы добавите больше параметров типа и отношений подтипов между различными универсальными интерфейсами, все довольно быстро станет неуправляемым.

18
задан stakx supports GoFundMonica 15 January 2012 в 10:06
поделиться