Перегрузка методов Delphi с неоднозначными типами параметров приводит к неожиданному выполнению

У меня есть два метода Equal, которые принимают эти перегрузки:

TVariantExpression = reference to function(): Variant;

function Equal(const value: Variant): TRuleBuilder; overload;
function Equal(expr: TVariantExpression): TRuleBuilder; overload;

предположим, что у меня есть другая функция:

function TForm1.GetMagicNumber: Variant;
begin
  Result := 10;
end;

и я вызываю такую ​​функцию:

Equal(Form1.GetMagicNumber);

После проверки, я получаю результат, вызванный второй перегрузкой. Зачем? потому что оба они действительны для вызова.

5
nl ja de
@arioch Использование @ на процедурных значениях почти всегда очень плохая идея. Он выводит вас за пределы системы типов. И заставляет тебя бросить.
добавлено автор David Heffernan, источник
@ Arioch'The Я не вижу, как $ T + помогает здесь. Я также всегда работаю в режиме $ T +.
добавлено автор David Heffernan, источник
@ Arioch'The Вы когда-нибудь пробовали присваивать @ Button1Click переменную типа TNotifyEvent ? Посмотрите, сколько вам поможет $ T + .
добавлено автор David Heffernan, источник
Я не знаю, почему, но, проверив, используя регистратор, чтобы определить, какая перегрузка, которая вызвала, я получаю, что второй вызов overlaod вызывается.
добавлено автор Niyoko Yuliawan, источник
не совсем. Адрес для функции будет @ Form.GetMagicNumber - и этот адрес еще должен быть указан с помощью функции объекта на ссылку на функцию ). Поэтому я думаю, что вы либо сделаете промежуточную ссылку ссылкой на функцию , либо попробуете явный TVariantExpression (@ Form.GetMagicNumber) . Pascal не является C ++, где любое имя функции является указателем по определению.
добавлено автор Arioch 'The, источник
Ну, я всегда работаю в режиме $ T + ;-)
добавлено автор Arioch 'The, источник
Тогда как он «вынимает из системы типов»?
добавлено автор Arioch 'The, источник
Ничего себе, такая добыча! спасибо вам обоим, нужно было бы это знать.
добавлено автор Arioch 'The, источник
Если вы используете @functionname, компилятор пропускает параметры и возвращает тип проверки, даже если у вас есть T +. Я сам столкнулся с этой проблемой. Код, который работал в течение многих лет, разбился, потому что кто-то добавил дополнительный параметр, но с @ -modifier компилятор не жаловался на несоответствие параметров.
добавлено автор Andreas Hausladen, источник

2 ответы

Form1.GetMagicNumber

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

В вашем коде значение имеет смысл. В таком сценарии языковые правила означают, что интерпретация процедурного типа выбрана.

Для принудительного вызова функции напишите:

Form1.GetMagicNumber()

Это существенное отличие от большинства других языков, например. C, C ++, C#, Java, Python и т. Д. На этих языках вы должны использовать круглые скобки для вызова функции.

7
добавлено
Я считаю, что это правильно. Это легко проверить.
добавлено автор David Heffernan, источник
Предположим, во-первых, у меня только первая перегрузка. И потребитель функции call Equal (Form1.GetMagicNumber); . Это будет совершенно верно. Позже я добавляю вторую перегрузку. Это будет тихо менять реализацию, которая называется. Правильно?
добавлено автор Niyoko Yuliawan, источник
Ха-ха .. Я думаю, что это приведет к ошибкам, которые довольно сложно отследить. И без знаковой подписи Equal мы даже не знаем, что Equal (Form1.GetMagicNumber); сделать.
добавлено автор Niyoko Yuliawan, источник

это потому, что первая равная функция имеет один и тот же параметр второго эквалайзера!

Когда вы выполняете $ (TVariantExpression = ссылка на функцию (): Variant;) , TVariantExpression принимает тип Variant как значение.

1
добавлено
Delphi & Lazarus
Delphi & Lazarus
274 участник(ов)

Чат про Delphi и Lazarus