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

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

问题描述

请考虑以下内容:

  {$ APPTYPE CONSOLE} 

使用
泛型收藏品

type
TObjProc =对象的过程;
TFoo = class
public procedure DoFoo;
公共程序DoBar;
结束

程序TFoo.DoFoo;
begin
WriteLn('foo');
结束

程序TFoo.DoBar;
begin
WriteLn('bar');
结束

var
ProcList:TList< TObjProc> ;;
Foo:TFoo;
aProc:TObjProc;
begin
Foo:= TFoo.Create;
ProcList:= TList< TObjProc> .Create;
ProcList.Add(Foo.DoFoo);
ProcList.Add(Foo.DoBar);
forProc在ProcList do aProc;
ReadLn;
结束。

这将产生



<$ p的预期输出$ p> foo
bar

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

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

但是这会导致编译器错误

  aProc:= ProcList.First; 
// E2010不兼容的类型:
//'procedure,untyped pointer or untyped parameter'和'TObjProc'

 功能TList  .First:T; 
begin
结果:= Items [0];
结束

所以...发生了什么?



这是否也会影响更新的Delphi版本?如果有一个合理的期望,这个应该是有效的(我认为是这样的),我很想QC。

解决方案

这是一个不是编译器的bug,这个问题与你使用泛型是没有关系的。 第一个 Last 是函数,所以编译器不能告诉你是打算调用它们还是引用它们。明确的是让编译器知道你的意思是通过提供括号来调用函数。

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

再次,您已经被确定为允许在调用程序时省略括号,功能。这种设计决策在制作时看起来很有吸引力,现在看起来更少,因为程序类型在现代编码风格中被广泛使用。



当你写 ProcList.First 编译器面临着歧义。您是否打算调用该函数,或者您是否希望将该函数称为过程类型?在许多情况下,编译器无法解决歧义,但是并非如此,在赋值运算符的右侧可以看到表达式。面对这种歧义,编译器假定你是指这个函数。



需要这个选择,因为其他选择会更糟。至少这样你可以提供括号,并明确指出你的意思是要调用的函数。编译器要按照其他方式进行,那么你将会找到一种方法来告诉它你是指这个函数。



最后,如果 First Last 已经被实现为属性,那将是没有歧义。


Consider the following :

{$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.

This produces the expected output of

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;

But this throws a compiler error :

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

Which is doubly odd since

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

So... what's going on?

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).

解决方案

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.

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.

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

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

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