Универсальный TThis для беглых классов

Я создаю свободный интерфейс, в котором у меня есть базовый класс, содержащий большую часть плавной логики, и производный класс, который добавляет некоторое специализированное поведение. Проблема, с которой я сталкиваюсь, — это тип возвращаемого значения быстрых методов в базовом классе при вызове из экземпляра производного типа. После вызова метода базового класса только методы базового класса остаются доступными для дальнейших быстрых вызовов.

Изменение порядка, в котором вызываются методы, поможет ему скомпилироваться, но сделает его менее читаемым, что в некотором роде важно для быстрых интерфейсов. Есть ли способ определить какой-то тип This для базового класса, чтобы все методы возвращали один и тот же тип.

Пример

public class Field<T>
{
    public Field<T> Name( string name )
    {
        _name = name;
        return this;
    }
}

public SpecialField<T> : Field<T>
{
    public SpecialField<T> Special(){ return this; }
}


// !!! Arrgh. Special is not a member of the Field<T> class.
var specialField = new SpecialField()
    .Name( "bing" )
    .Special();

Сломанное решение

Я пытался решить это, выполнив что-то вроде следующего, но это недопустимо для С# :( но, по крайней мере, выражает то, как я хотел бы закодировать интерфейс.

public class Field<T,TThis> : TThis
    where TThis : Field<T,TThis>
{
    public TThis Name( string name ){...}
}

public SpecialField<T> : Field<T,SpecialField<T>>
{
    public TThis Special(){ return this; }
}

person Paul Alexander    schedule 05.11.2009    source источник


Ответы (1)


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

Образец

public class FieldBase<T,TThis> 
    where TThis : FieldBase<T,TThis>
{
    private string _name;
    public TThis Name( string name ) 
    {
        _name = name;
        return (TThis)this;
    }
}

public class Field<T> : FieldBase<T,Field<T>>{}

public class SpecialFieldBase<T,TThis> : FieldBase<T,TThis>
    where TThis : SpecialFieldBase<T,TThis>
{
    public TThis Special(){ return (TThis)this; }
}

public class SpecialField<T> : SpecialFieldBase<T,SpecialField<T>>{}


// Yeah it works!
var specialField = new SpecialField<string>()
    .Name( "bing" )
    .Special();
person Paul Alexander    schedule 05.11.2009
comment
Это похоже на ковариантность и контравариантность. blogs.msdn.com/ b/csharpfaq/archive/2010/02/16/ В книге «Теория объектов» они тратят один или два раздела на обсуждение трудностей, которые представляет собой самость для набора текста, поэтому выяснение того, как типизировать себя или это является основной мотивацией вопросов о ко- и контравариантности. lucacardelli.name/TheoryOfObjects.html - person Dennis; 06.10.2011