Тип возврата при использовании любопытно повторяющегося шаблона - PullRequest
1 голос
/ 14 ноября 2011

Я использую странно повторяющийся шаблон (CRTP) в моем проекте на C #, но у меня возникли некоторые проблемы. Код взломан по ссылке выше:

public abstract class Base<T> where T : Base<T>{
    public T FluentMethod() {
        return (T)(this); 
    }
}

public class Derived : Base<Derived> {
}

Красивая! Проблема возникает, когда я пытаюсь сделать что-то вроде этого:

public class SomeClass
{
    Base<T> GetItem() { /* Definition */ };
}

SomeClass должен иметь возможность возвращать любую реализацию класса Base, но, разумеется, T не имеет здесь никакого значения, так как это происходит в другом классе. Помещение Derived вместо T компилируется, но это не то, что я хочу, так как я должен иметь возможность возвращать элементы других типов, если они получены из Base. Кроме того, GetItem () может возвращать различные типизированные объекты в зависимости от состояния объекта SomeClass, поэтому создание универсального SomeClass также не является решением.

Я что-то упускаю здесь очевидное или это нельзя сделать при использовании CRTP?

Ответы [ 2 ]

3 голосов
/ 14 ноября 2011

Вы должны объявить метод как универсальный:

using System;
public abstract class Base<T> where T : Base<T> {
    public T FluentMethod() {
        return (T)(this);
    }
}

public class Derived : Base<Derived> {
}

public class SomeClass {
    Base<T> GetItem<T>() where T : Base<T> {
        throw new NotImplementedException();
    }
}

Чтобы сделать его свойством, вы должны объявить сам класс как общий:

public class SomeClass<T> where T : Base<T> {
    Base<T> GetItem {
        get { throw new NotImplementedException(); }
    }
}
0 голосов
/ 14 ноября 2011

Не делайте публичный метод универсальным, иначе объявление типа достигнет другого уровня.Создайте фабричный класс для разных типов, таких как «Derived GetDerivedItem ()»

public class SomeClass {
    private Base<T> GetItem<T>() { /*implementation */ }

    public Derived GetDerivedItem() {
        return GetItem<Derived>();
    }
}
...