Общие ограничения на производные классы - PullRequest
8 голосов
/ 24 октября 2008

У меня есть класс A:

public class ClassA<T>

Класс B является производным от A:

public class ClassB : ClassA<ClassB>

Класс C является производным от класса B:

public class ClassC : ClassB

Теперь у меня есть универсальный метод с ограничениями

public static T Method<T>() where T : ClassA<T>

ОК, теперь я хочу позвонить:

ClassC c = Method<ClassC>();

но я получаю сообщение об ошибке: Type argument 'ClassC' does not inherit from or implement the constraint type 'ClassA<ClassC>.

Тем не менее, компилятор позволит:

ClassB b = Method<ClassB>();

Насколько я понимаю, это терпит неудачу, потому что ClassC наследует ClassA<ClassB> вместо ClassA<ClassC>

Мой реальный вопрос: возможно ли создать класс, производный от ClassB, который можно каким-то образом использовать с универсальным методом?

Может показаться, что дженерики чрезмерно используются, и я бы согласился. Я пытаюсь создать объекты бизнес-уровня на основе дозвуковых объектов данных в отдельном проекте.

Примечание: я поставил с лишними пробелами, иначе они будут удалены из вопроса.

Ответы [ 3 ]

6 голосов
/ 24 октября 2008

Ну, вы можете изменить метод на:

public static T Method<T,U>() where T : ClassA<U> where U : T

Помогает ли это вообще? Это не очень полезно, если вы не можете изменить метод, конечно ...

2 голосов
/ 24 октября 2008

Нет. Вы должны изменить или обернуть этот метод.

Вот причина.

ClassC наследуется от ClassB, который наследуется от ClassA (ClassB)

ClassC не наследуется от ClassA (ClassC)

Ни один дочерний объект ClassB не наследует от ClassA (дочерний класс), поскольку вместо этого они наследуют от ClassB, а ClassB не наследует от ClassA (дочерний класс).

Универсальные типы инвариантны .

1 голос
/ 24 октября 2008

В большинстве случаев этот сценарий можно решить с помощью базового неуниверсального абстрактного класса:

public abstract class BasicClassA
{
}

public class ClassA<T> : BasicClassA
{
}

public class ClassB : ClassA<ClassB>
{
}

public class ClassC : ClassB
{
}

public static T Method<T>() where T : BasicClassA
{
    return null;
}

Ваш пробег может варьироваться.

...