泛型不能正确解析方法类型 [英] Generics not resolving method types correctly

查看:23
本文介绍了泛型不能正确解析方法类型的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

考虑以下几点:

{$APPTYPE CONSOLE}

uses
  Generics.Collections;

type
  TObjProc = procedure of object;
  TFoo = class
    public procedure DoFoo;
    public procedure DoBar;
  end;

procedure TFoo.DoFoo;
begin
  WriteLn('foo');
end;

procedure TFoo.DoBar;
begin
  WriteLn('bar');
end;

var
  ProcList : TList<TObjProc>;
  Foo : TFoo;
  aProc : TObjProc;
begin
  Foo := TFoo.Create;
  ProcList := TList<TObjProc>.Create;
  ProcList.Add(Foo.DoFoo);
  ProcList.Add(Foo.DoBar);
  for aProc in ProcList do aProc;
  ReadLn;
end.

这会产生

foo
bar

现在假设我们要从列表中分配一个过程.枚举工作,如上.这也有效:

Now suppose we want to assign a procedure from the list. Enumerating works, as above. This also works:

aProc := ProcList.Items[0];
aProc;

但这会引发编译器错误:

aProc := ProcList.First;
// E2010 Incompatible types: 
//'procedure, untyped pointer or untyped parameter' and 'TObjProc'

这很奇怪,因为

function TList<T>.First: T;
begin
  Result := Items[0];
end;

所以……发生了什么?

这是否也会影响较新版本的 Delphi?如果有合理的预期认为这应该可行(我认为确实如此),我很想对此进行 QC.

Does this affect newer versions of Delphi as well? I'm tempted to QC this if there is a reasonable expectation that this should work (which I think there is).

推荐答案

这不是编译器错误,也确实与您使用泛型无关.FirstLast 都是函数,因此编译器无法判断您是要调用它们还是引用它们.明确并让编译器知道您的意思是通过提供括号来调用函数.

This is a not a compiler bug, nor indeed is this issue related to your use of generics. Both First and Last are functions so the compiler cannot tell whether you mean to call them, or reference them. Be explicit and let the compiler know that you mean to call the function by supplying parens.

aProc := ProcList.First();
aProc := ProcList.Last();

您再次被允许在调用过程和函数时省略括号的决定所困扰.这个设计决定虽然在做出时看起来很吸引人,但现在看起来不那么吸引人了,因为程序类型在现代编码风格中被如此广泛地使用.

Yet again you have been caught out by the decision to allow the parens to be omitted when invoking procedures and functions. This design decision, whilst looking so appealing when it was made, is looking less so now that procedural types are so widely used in modern coding styles.

当您编写 ProcList.First 时,编译器会面临歧义.您是要调用该函数,还是希望将该函数称为过程类型?在许多情况下,编译器无法解决歧义,但这里的情况并非如此,表达式位于赋值运算符的右侧.面对这种歧义,编译器假定您要引用该函数.

When you write ProcList.First the compiler faces an ambiguity. Do you mean to call the function, or are you wishing to refer to the function as a procedural type? In many scenarios, the compiler cannot resolve the ambiguity, but that is not the case here, where the expression is found on the right hand side of an assignment operator. Faced with this ambiguity the compiler assumes that you mean to refer to the function.

做出这个选择是因为另一个选择会更糟.至少通过这种方式,您可以提供括号并明确表明您的意思是要调用该函数.如果编译器走另一条路,那么您将不得不寻找一种方法来告诉它您打算引用该函数.

It takes this choice because the other choice would be worse. At least this way you can supply the parens and explicitly indicate that you mean for the function to be called. Were the compiler to go the other way then you'd be left looking for a way to tell it that you meant to refer to the function.

最后一点,如果 FirstLast 被实现为属性,就不会有歧义.

As a final aside, if First and Last had been implemented as properties there would have been no ambiguity.

这篇关于泛型不能正确解析方法类型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆