Jump to content
David Schwartz

Anon methods passed as event handlers?

Recommended Posts

1 hour ago, Rudy Velthuis said:

C# delegates are terribly complex, and that is why they work the way they do. Delphi has more or less lightweight implementations for procedural and method types. Good for us.

 

So I'll repeat it:  If people want the complexity of C#, then they should use C#.

They really aren't complex at all to use. Which is my point. You are talking about the implementation details.

 

If you find C# complex then that's on you. Since you declared a few comments back that you didn't really have a sound grasp of C# delegates perhaps you should become knowledgeable on the subject before acting like an expert. Just a thought. 

 

Myself, I don't find C# delegates at all complex. It would certainly be pretty convenient if you could use anon methods as event handlers, as you can trivially do in C#. I understand why you can't in Delphi and it's too late to change now. But when you write code in other languages that don't have backwards compatability constraints, it can be irritating when you come back to Delphi. 

Share this post


Link to post
Posted (edited)
19 hours ago, David Heffernan said:

David is making a good point here. If Emba were starting from scratch here, would they end up with all these different incompatible procedural types? I doubt it. 

Yes, I guess so (i.e, I don't doubt it). You can assign a normal procedural type and a method to a "reference to" pointer, but the latter is not really a simple type. Compared to them, procedural types and method pointers are far more lightweight.

 

If they had used something like anonmeths for events from the start, I am sure that people would already have called for simpler types instead, like what we have now.

Edited by Rudy Velthuis

Share this post


Link to post
Posted (edited)
2 hours ago, David Heffernan said:

They really aren't complex at all to use. Which is my point. You are talking about the implementation details.

 

If the "implementation details" make them much heavier (i.e. have much more overhead), because they require the

generation of an object and an interface and the capture of local variables, then these details do matter.

 

The current types are also easy enough to use. Yes, there is sometimes confusion about the fact you can't assign

a simple prodcedure to an event, but that is it. That is is not a good reason to use all these complex types everywhere. 

 

Heck, even if a proper event method explicitly has to call a simple procedure, then that is still far less overhead than

an anonmeth.

Edited by Rudy Velthuis

Share this post


Link to post
1 hour ago, Chris Rolliston said:

By the by, this historical piece is quite an amusing read:

 

https://web.archive.org/web/20120627043929/http://java.sun.com/docs/white/delegates.html

 

Sun's reply to Microsoft adding delegate types to its Windows-centric version of Java (Visual J++ being Anders Hejlsberg's main project in between Delphi and C# I think...?).

Quote

This decision was made in consultation with Borland International, who had previous experience with bound method references in Delphi Object Pascal.

LOL!

 

It seems they mean method pointers in Delphi, especially how they were used for events, and they don't want them. Ok, their decision.

 

When I first saw events at work (a demo at CeBit 1995) I was impressed. The VCL and especially the way properties and events worked were the main reason I ordered Delphi 1 at the spot. I don't care if they are pure OOP (I actually don't see why not).

Share this post


Link to post
11 hours ago, Rudy Velthuis said:

Also, an event needs two things: an object and a code pointer. It can't do without. A plain or static function does not have those, An anonymous method does not necessarily have these either.

And yet, it CAN be done with plain/static functions.  I do it all the time when writing test apps that have no UIs.  It is just a matter of adding an explicit Self parameter to the function, populating a TMethod record with the address of the function in the Code field and an arbitrary value in the Data field, and then assigning that TMethod to the target event via a type-cast.

Share this post


Link to post
9 hours ago, Remy Lebeau said:

And yet, it CAN be done with plain/static functions.  I do it all the time when writing test apps that have no UIs.  It is just a matter of adding an explicit Self parameter to the function, populating a TMethod record with the address of the function in the Code field and an arbitrary value in the Data field, and then assigning that TMethod to the target event via a type-cast.

FWIW: If I have to adapt the interface of the routine anyway I would make it into a (non-static) class method of a dummy class and stay completely inside of the type system.

Share this post


Link to post
19 hours ago, Remy Lebeau said:

And yet, it CAN be done with plain/static functions.  I do it all the time when writing test apps that have no UIs.  It is just a matter of adding an explicit Self parameter to the function, populating a TMethod record with the address of the function in the Code field and an arbitrary value in the Data field, and then assigning that TMethod to the target event via a type-cast.

Yeah, well, you can do a lot when cheating.

Share this post


Link to post
10 hours ago, uligerhardt said:

FWIW: If I have to adapt the interface of the routine anyway I would make it into a (non-static) class method of a dummy class and stay completely inside of the type system.

Yes, indeed, so would I. But you have to create and free those, to really stay inside the type system.

Share this post


Link to post
Posted (edited)
10 hours ago, Rudy Velthuis said:

Yes, indeed, so would I. But you have to create and free those, to really stay inside the type system.

No, that's why I'm talking about class methods. You can use them like this:

type
  TMyEventHandler = class
  public
    class procedure OnError(const AMessage: string);
  end;

Something.OnError := TMyEventHandler.OnError;

The method has to be non-static to provide the needed Self parameter.

Edited by uligerhardt
Typo, syntax highlighting, clarification
  • Like 3

Share this post


Link to post
3 hours ago, uligerhardt said:

No, that's why I'm talking about class methods. You can use them like this:


type
  TMyEventHandler = class
  public
    class procedure OnError(const AMessage: string);
  end;

Something.OnError := TMyEventHandler.OnError;

The method has to be non-static to provide the needed Self parameter.

Oh, Ok, I understand what you mean. Yes, that's possible.

Share this post


Link to post
On 5/5/2019 at 2:51 AM, uligerhardt said:

I would make it into a (non-static) class method of a dummy class and stay completely inside of the type system.

Sometimes I do that, too.  But writing a class to wrap a standalone function is not always as convenient as just using the function by itself.

Share this post


Link to post
On 5/5/2019 at 1:30 PM, Rudy Velthuis said:

Yes, indeed, so would I. But you have to create and free those, to really stay inside the type system.

You don't have to create instances of the class if you use a non-static 'class' method for the event handler.  It still has an implicit Self parameter, but it points to the class type instead of an object instance.  Works fine with events, as long as the method doesn't need to access any members of a particular object instance.

Share this post


Link to post
1 hour ago, Remy Lebeau said:

You don't have to create instances of the class if you use a non-static 'class' method for the event handler.

Yes, I got that already, thanks.

Share this post


Link to post

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×