J..*_*... 12 delphi generics delphi-xe2
考虑以下 :
{$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.
Run Code Online (Sandbox Code Playgroud)
这产生了预期的输出
foo
bar
Run Code Online (Sandbox Code Playgroud)
现在假设我们要从列表中分配一个过程.列举作品,如上所述.这也有效:
aProc := ProcList.Items[0];
aProc;
Run Code Online (Sandbox Code Playgroud)
但这会引发编译器错误:
aProc := ProcList.First;
// E2010 Incompatible types:
//'procedure, untyped pointer or untyped parameter' and 'TObjProc'
Run Code Online (Sandbox Code Playgroud)
这是多么奇怪的事
function TList<T>.First: T;
begin
Result := Items[0];
end;
Run Code Online (Sandbox Code Playgroud)
发生什么了?
这是否也会影响较新版本的Delphi?如果有一个合理的期望,这应该有效(我认为有),我很想QC.
Dav*_*nan 14
这不是编译器错误,也不是这个问题与您使用泛型有关.这两个First和Last的功能,因此编译器不能告诉你是否是说给他们打电话,或引用它们.明确,让编译器知道您的意思是通过提供parens来调用该函数.
aProc := ProcList.First();
aProc := ProcList.Last();
Run Code Online (Sandbox Code Playgroud)
然而,在调用过程和函数时,允许删除parens的决定再次让你感到困惑.这个设计决定虽然在制作时看起来如此吸引人,但由于程序类型在现代编码风格中被如此广泛地使用,因此看起来不那么重要.
当你编写ProcList.First编译器时面临歧义.您是要调用该函数,还是希望将该函数称为过程类型?在许多情况下,编译器无法解决歧义,但这不是这里的情况,其中表达式位于赋值运算符的右侧.面对这种歧义,编译器假定您要引用该函数.
需要这个选择,因为另一个选择会更糟.至少通过这种方式,您可以提供parens并明确指出您要调用的函数.如果编译器走向另一个方向,那么你将继续寻找一种告诉它你想要引用该函数的方法.
最后,如果First并且Last已经作为属性实现,那么就没有歧义.
| 归档时间: |
|
| 查看次数: |
255 次 |
| 最近记录: |