Anonymous Methods and Delegates

From The Oxygene Language Wiki

Jump to:navigation, search

This is a Language topic
Feel free to add your notes to this topic below.



Anonymous methods and delegates are extremely powerful features in Delphi Prism, that can not only spare you a lot of time and lines of code, but can make your code much more readable, especially when working with threads that have to access the GUI.

The basics for both anonymous methods and delegates will be explained with an example application: A WPF application that will fill a listbox with numbers using an asynchronous method. Without anonymous methods, the application looks like this:


Sample without any anonymous things

The asynchronous method uses the .NET Dispatcher class to invoke a method in the GUI's thread. This method matches the signature of delegates defined only for this purpose.

type
  AddToListBox = public method(nr : Integer);

method Window1.DoAddToListBox(nr : Integer);
begin
  numbersListBox.Items.Add(nr);
end;

method Window1.GetNumbers; //declared as async in the interface
begin
  for i : Integer := 0 to Integer.MaxValue do
    Dispatcher.Invoke(DispatcherPriority.ApplicationIdle, new AddToListBox(@DoAddToListBox), i);
end;

Now we have a delegate and a method, just to add some numbers to a listbox!

Anonymous Methods

Anonymous methods are methods that are implemented inside the code of another method by the programmer. The compiler will, of course, create a "normal" method, but the programmer won't have to declare a method in the interface or give it a name. That's why they're called "anonymous" methods. In our example code it looks like this:

type
  AddToListBox = public method(nr : Integer);

method Window1.GetNumbers; //declared as async in the interface
begin
  var aMethod : AddToListBox := method(nr : Integer);
    begin
      numbersListBox.Items.Add(nr);
    end;

  for i : Integer := 0 to Integer.MaxValue do
    Dispatcher.Invoke(DispatcherPriority.ApplicationIdle, aMethod, i);
end;

Now, we don't have to declare an extra method, the compiler is doing that for us. (It creates a whole new class containing that method and holding a reference to our Window1 class.)

Anonymous Delegates

Anonymous delegates make it possible to let the compiler declare a delegate with a signature, matching an (anonymous) method. In our example code it looks like this:

method Window1.GetNumbers;  //declared as async in the interface
begin
  for i : Integer := 0 to Integer.MaxValue do
    Dispatcher.Invoke(DispatcherPriority.ApplicationIdle, method(nr : Integer); begin
      numbersListBox.Items.Add(nr);
    end, i);
end;

That's all. No delegate, no method in the interface section. Again, the new class is created with a method matching this signature.

Anonymous methods without parameters

When omitting the parameter declaration for an anonymous method declaration, Delphi Prism will try to create a matching method declaration that fits into the delegate given, but the parameters won't be accessible from inside the method.

if(Self.InvokeRequired) then begin
    Invoke(
      method
      begin 
        //...
      end
    );

Using local variables in anonymous methods

Currently we pass the variable i as parameter to our anonymous method, but that's not necessary: we can just use the local variable i in the anonymous method and omit the parameter:

method Window1.GetNumbers;  //declared as async in the interface
begin
  for i : Integer := 0 to Integer.MaxValue do
    Dispatcher.Invoke(DispatcherPriority.ApplicationIdle, method; begin
      numbersListBox.Items.Add(i);
    end);
end;

Now the compiler-created class with "our" method is extended by a field containing the value of our local variable i, so that the anonymous method can access it. Note that any change to the I in the outside scope (the method) will influence the value of I inside the anonymous, so anonymous methods that aren't called till later might have unexpected values if the parent scope changes the variable later on.

Pros and Contras

The benefits when using anonymous methods and delegates are obvious: Especially when using them to access different threads, they make it possible to write code that looks almost as if it was executed "normally", although it is executed in a different thread. You don't have to contaminate your code with hundreds of mini methods and dozens of different delegates, which also improves your productivity.

But use this feature wisely: Having to declare methods and having an interface section is what makes pascal code readable. If you use too many anonymous methods and delegates, your code will be less readable.


Oxygene-48.png

Area: Oxygene Language
Compiler version: Oxygene 5

Language GlossaryKeywordsTypesFAQHow To

Navigation
Areas
More
Toolbox