2014-10-01 1 views
11

다음의 고려 방법의 종류를 해결하지 :제네릭이 제대로

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

의 예상 출력을 생성합니다. 위와 같이 열거가 작동합니다.

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

을하지만 이것은 컴파일러 오류가 발생합니다 : :이 또한 작동 그래서

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

이후 이중 홀수

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

을 ... 무슨 일이야?

이것은 최신 버전의 Delphi에도 영향을 줍니까? 이것이 제대로 작동해야한다는 합리적인 기대가 있다면 QC에 유혹을 받는다.

답변

13

이것은 컴파일러 버그가 아니며 generics 사용과 관련된 문제도 아닙니다. FirstLast은 모두 함수이므로 컴파일러는 해당 함수를 호출하거나 참조 할 것인지 여부를 알 수 없습니다. 명시 적으로 컴파일러가 paren을 제공하여 함수를 호출한다는 것을 알리십시오.

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

프로 시저 및 함수를 호출 할 때 괄호를 생략하도록 허용 한 결정에 의해 다시 캐치되었습니다. 이 디자인 결정은 그것이 만들어 졌을 때 매우 호소력있게 보이지만 절차 적 유형이 현대적인 코딩 스타일에서 널리 사용됨에 따라 그다지 관심을 보이지 않습니다.

ProcList.First을 쓸 때 컴파일러의 모호성이 있습니다. 함수를 호출하려고하거나 함수를 프로 시저 유형이라고 지칭하고 싶습니까? 많은 시나리오에서 컴파일러는 모호성을 해결할 수 없지만 대입 연산자의 오른쪽에식이있는 경우는 아닙니다. 이 모호성에 직면하여 컴파일러는 함수를 참조하는 것을 의미한다고 가정합니다.

다른 선택이 더 나쁠 것이므로이 선택을 취합니다. 적어도 이런 식으로 괄호를 제공하고 함수 호출을 의미한다는 것을 명시 적으로 나타낼 수 있습니다. 컴파일러가 다른 방향으로 가면 함수를 참조한다는 의미를 알 수있는 방법을 찾아야합니다.

마지막으로, FirstLast이 속성으로 구현 된 경우 모호성이 없었을 것입니다.

+2

C#, C, C++, Python 및 기타 모든 언어에서. VB는 따로하고. 크기가 2 세트이고 다른 멤버가 VB 일 때 항상 나빠질 수 있습니다! –

+0

그리고, AFAIK, Swift, 그럼 3 세트가됩니다. –