2014-12-03 13 views
5

Lassen Sie uns sagen, dass ich eine Klasse mit zwei generische Methoden haben:Allgemeine Methoden Typinferenz

TMyClass = class 
    procedure DoWith<T: class> (obj: T); 
    procedure DoFor<T: class> (proc: TProc<T>); 
end; 

Nun, wenn ich eine dieser beiden Methoden mit einem bestimmten Typparameter aufrufen möchten, können Delphi den Typ für die folgern DoWith Methode, so kann ich es mit rufen entweder

MyClass.DoWith <TButton> (MyButton) 

oder

MyClass.DoWith (MyButton) 

Der Delphi-Compiler kompiliert beide gerne. Aber wenn ich die Typ-Parameter in der DoFor Methode weglassen, klagen die Delphi-Compiler über die fehlenden Typen Parameter:

MyClass.DoFor<TButton>(procedure (Button: TButton) begin .... end); // compiles 


MyClass.DoFor(procedure (Button: TButton) begin .... end); // doesn't compile 

Jetzt ist meine Frage: Ist das nur ein Manko des Compilers, oder es ein logischer Grund (das habe ich noch nicht herausgefunden), die es dem Compiler verbietet, den Typ für die DoFor Methode richtig abzuleiten?

+0

Es sieht aus wie eine Beschränkung des Compilers. Generische Inferenz ist in Delphi sehr schwach. –

Antwort

5

Der Grund ist es nicht T aus einem TProc<T> Argumente ableiten kann, ist, dass TProc<TButton> zu diesem Zeitpunkt eine Art ohne jede Information konstruiert ist, dass es ursprünglich ein TProc<T> war.

Dazu müsste man den Typ aus der anonymen Methodensignatur ableiten, der nicht funktioniert (Barry Kelly könnte das besser erklären und ich glaube, er hat einmal über die Schwierigkeiten von lambdas geschrieben und schließt in Delphi).

Die einzige Typ-Inferenz, zu der der Delphi-Compiler fähig ist, ist ein Argument vom Typ T. Auch mit mehreren Argumenten funktioniert das nicht oft und noch weniger, wenn Sie mehr als einen generischen Typparameter haben.

Edit: Ich habe einen Kommentar gefunden, wo Barry ein wenig über die Schwierigkeiten der Typinferenz und Lambda-Ausdrücke in den Delphi-Compiler erklärt: http://www.deltics.co.nz/blog/posts/244/comment-page-1#comment-107

+0

Danke Stefan: Deine Antwort gab mir die fehlenden Bits, um zu verstehen, dass es einen logischen Grund für dieses Compilerverhalten gibt. – iamjoosy

+1

@iamjoosy Ich persönlich finde das unlogisch. Ich würde es bevorzugen, wenn der Compiler die Typen viel besser ableitet. Ich sehe keinen Grund, warum es das nicht könnte. Viele andere Sprachen schaffen das weitaus besser als Delphi. –

+0

@DavidHeffernan Zuerst konnte ich im Compilerverhalten selbst keine Logik erkennen, daher meine Frage hier. Aber Stefans Antwort hat mir die Augen geöffnet, indem ich erklärt habe, wie der Compiler den Ausdruck behandelt: Er konstruiert die eigentlichen Typen von innen nach außen und konstruiert zunächst die anonyme Funktion mit dem TButton-Typ und arbeitet dann mit diesem Typ in der umgebenden Prozedur und an dieser Stelle Compiler hat "vergessen", dass die anonyme Funktion aus dem gleichen Typparameter T konstruiert wurde, der die umgebende Funktion schmückt. – iamjoosy