C#2.0 Anonymous methods

 

 

All methods use a subset of elements from the same master set. In C# 2.0, the set of optional elements will grow. Historically—except in C++ inline methods—methods required a name, a return type, and a body. Optionally, methods could use an access modifier and a parameter list. In C# 2.0, the method name has been moved from the list of required items to the list of optional items.

C# 2.0 (and .NET in general) introduces the anonymous method. An anonymous method can be used anywhere a delegate is used and is defined inline, without a method name, with optional parameters and a method body.

Anonymous methods are a condensed way to declare and use delegates. Delegates started life in languages that preceded .NET languages, as pointers to function signatures. A delegate is a class that encapsulates the pointer; implicitly, delegates in .NET are multicast delegates. To be a multicast delegate simply means that the “one function to one pointer” limitation is gone, because the multicast delegate class contains a list of pointers. The inclusion of an internal list means that the address of more than one function can be assigned to a single delegate. When the delegate—think “event”—is raised or invoked, all of the internally listed functions are called.

 

In C#, the addresses of functions are inserted in a list via an overloaded += operator and removed via an overloaded -= operator. C# also supports manually defining add and remove blocks; add and remove are to delegates what get and set are to properties.

In C# 1.0 and C# 1.1, we typically assign instances of delegates to event properties. For example, in WinForms a Button control exposes a Click event. The delegate type of Click is EventHandler. EventHandler is a method that takes object and EventArgs arguments. Hence, we can initialize an EventHandler object with any method matching the delegate Event Handler’s signature and assign that delegate to Click. Here’s how the code might look:

private void Form1_Load(object sender, EventArgs e)
{
    button1.Click += new EventHandler(OnClick);
}
 
private void OnClick(object sender, EventArgs e)
{
    Debug.WriteLine("button1 clicked");
}

Because the forms designer for WinForms and the page designer for WebForms automatically add the code for delegate binding, it’s possible to write a lot of code without binding delegates manually.

Anonymous Methods Are Inline Delegates

Generally, when we’re using delegates, we have a method. That method’s signature matches the signature prescribed by a delegate and can be used to initialize a delegate instance. Anonymous methods are used to condense the method and initialization of the delegate into a single location.

Using the example from the previous section, we see how the instantiation of the delegate new EventHandler is distinct from the method OnClick used to initialize the delegate. This code could be compressed into an anonymous method:

private void Form1_Load(object sender, EventArgs e)
{
  button1.Click += delegate
  {
    Debug.WriteLine("button1 clicked");
  };
}

To create the anonymous method, notice that we removed OnClick‘s method header and replaced the construction of the EventHandler delegate with the word delegate followed by OnClick‘s method body. The resultant behavior is the same. If we want to use the event arguments we would normally find associated with the delegate, we can add an optional parameter list after the word delegate:

private void Form1_Load(object sender, EventArgs e)
{
  button1.Click += delegate(object s, EventArgs ev)
  {
    Debug.WriteLine("object is " + s.ToString());
  };
}

If you define delegate parameters, they must match the parameters defined by the delegate type. For example, Click‘s type is EventHandler, so if arguments are present they must match EventHandler‘s arguments object and EventArgs.

Anonymous methods can be used wherever delegates are expected. Anonymous methods can use ref and out arguments, but cannot reference ref or out parameters of an outer scope. Anonymous methods can’t use unsafe code, and anonymous methods can’t use goto, break, or continue in such a way that the branch behavior causes a branch outside of the anonymous method’s code block.

Use of Anonymous methods

Anonymous methods are good because they reduce code overhead caused by instantiating delegates and reducing separate methods. But the marketing material also says that anonymous methods increase usability and maintainability. I thought well-named methods did that. Does this code look easily maintainable?

private void Form1_Load(object sender, EventArgs e)
{
    BindClick(delegate { Debug.WriteLine("button1 click"); });
}
 
private void BindClick(EventHandler handler)
{
    button1.Click += handler;
}

In this sample, we’re passing a delegate to a method by passing the delegate as an anonymous method. Just keeping the order and number of the parentheses, semicolons, and brackets straight is a pain in the neck.

The cited classic example is that anonymous methods can reduce the overhead of creating delegates and methods just for kicking off threads (which use delegates). This is true, but threads are used infrequently and are already difficult enough to use correctly; I wonder how prudent it is to make the code more esoteric rather than less.

Anonymous methods are examples of methods without names that can be defined and used anywhere a delegate can be used. Delegates are wrappers for event handlers. How practical and generally useful anonymous methods are remains to be seen. I suspect that anonymous methods will be much less useful than overloaded operators and used even less frequently, but anonymous methods are part of .NET and it’s useful to recognize them when you see them.

 

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s