Использование собственного класса в качестве ограничения параметра типа в объявлении класса

У меня есть следующее объявление класса в Delphi XE8:

TestClass = class;
TestClass = class
  function test<T: TestClass>(supplier: TFunc<T>): T; // Compiler error
end;

Который выдает следующую ошибку компилятора:

E2086 Type 'TestClass' is not yet completely defined

Когда я добавляю в класс другой класс и использую его как ограничение, он работает нормально:

AnotherTestClass = class
end;

TestClass = class;
TestClass = class
  function test<T: AnotherTestClass>(supplier: TFunc<T>): T; // No Error
end;

Я подозреваю, что проблема заключается в том, что объявление типа forward недостаточно сообщает Delphi о TestClass типа еще. Это, возможно, более очевидно, поскольку следующая попытка обойти проблему выдает ту же ошибку компилятора в другой строке:

TestClass = class;
AnotherTestClass = class (TestClass) // Compiler Error
end;
TestClass = class
  function test<T: AnotherTestClass>(supplier: TFunc<T>): T;
end;

Я делаю что-то не так, и если нет, есть ли способ обойти эту проблему?

1 ответ

Решение

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

Обратите внимание, что в.net то, что вы пытаетесь сделать, вполне возможно:

class MyClass
{
    private static T test<T>(Func<T> arg) where T : MyClass
    {
        return null;
    }
}

Функция обобщений Delphi была основана на обобщениях.net, и я скорее подозреваю, что проблема, с которой вы сталкиваетесь, сводится к недосмотру со стороны разработчиков Delphi.

Вы должны отправить отчет об ошибке / запрос функции.

Обновление 1

LU RD предлагает лучший обходной путь. Используйте помощник класса:

type
  TestClass = class
  end;

  TestClassHelper = class helper for TestClass
    function test<T: TestClass>(supplier: TFunc<T>): T;
  end;

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

Обновление 2

Сообщение об ошибке: RSP-13348

Другие вопросы по тегам