Chapter 15. Delegates, Events, and Anonymous Methods

Although not directly related to user interaction per se, delegates and events form the fundamental building blocks upon which the GUI layer operates.

Delegates and events, in particular, are a way of decoupling various parts of your program. For example, by creating events for your components, they can signal changes in themselves, without needing to care about the interfaces of external components that are interested in finding out about those changes.

Anonymous methods and lambda expressions are in some ways merely simplifications of syntax when dealing with delegates.

Decide Which Method to Call at Runtime

Solution: Declare a delegate that matches the signature of the target methods. In C#, delegates are kind of like object-oriented, type-safe function pointers. They can also be generic. This example shows how delegates can be aggregated and stored like any other piece of data, and then executed.

image

image

Call Multiple Methods with a Single Delegate

Solution: All delegates are automatically what are called multicast delegates, which means that you can assign multiple target methods to them. This is done using the += operator.

image

Note

In the first delegate example, the delegate methods returned values. This is perfectly legal for multicast delegates, but the return value for non-void delegate invocations will be the return value of the final method called. This is rather nondeterministic, so most delegates are of return type void.

Subscribe to an Event

Solution: Use .NET’s event-handling syntax to add your handler to the event’s delegate list.

This example subscribes to the Button’s Click event:

image

Stop Subscription to an Event

Solution: Use the -= syntax to remove your event handler. Here’s an example:

button1.Click -= new EventHandler(button1_Click);

Publish an Event

Solution: Create an event in your class that anyone else can subscribe to. You should follow the established event-raising pattern established in the .NET Framework, as demonstrated in the following example.

This example simulates the loading of program data on a second thread, which notifies the main thread when it’s complete:

image

image

image

image

Ensure UI Updates Occur on UI Thread

Solution: You must invoke the required method on the UI thread.

Because of the way they’re implemented internally, Windows UI elements must be accessed on the same thread that created them. Previous frameworks (such as MFC) didn’t enforce this so much, but .NET does. Windows Forms and WPF handle this slightly differently.

In WinForms

In WinForms, you can check if you’re running on the UI thread by polling InvokeRequired on any UI element. If it’s true, you need to switch to the main thread by calling Invoke() and passing it a delegate.

In practice, there are a few ways to do this, but an easy way (from the previous example) is demonstrated in the data_LoadStarted event handler:

image

In WPF

In WPF, the concept is similar. Each WPF element has a property called Dispatcher. By comparing the Dispatcher’s thread to the current thread, you can tell when you need to call Invoke. The following example demonstrates this in a simple WPF app (see the WpfInvoke sample project):

image

image

Assign an Anonymous Method to a Delegate

Solution: Use the anonymous method syntax to assign a block of code to a delegate.

image

Use Anonymous Methods as Quick-and-Easy Event Handlers

Solution: Assign an anonymous method to the delegate using syntax like that in the following example:

image

Figure 15.1 demonstrates the AnonymousMethods sample project, from the sample code for this chapter.

Figure 15.1 Anonymous methods often make sense for quick event handlers.

image

Use Lambda Expression Syntax for Anonymous Methods

Solution: Use the lambda expression syntax for anonymous methods. Lambda expressions can be used for anonymous methods, as well as to create expression trees in LINQ. This code does the same thing as the previous example:

image

Take Advantage of Contravariance

Solution: In .NET 4, contravariance on delegates fixed this to enable you to assign less-specific delegates to more-specific delegates, as long as the type parameter T is declared as “in,” which means the delegate does not return T. In the following code, the delegate’s type parameter has been modified with in.

image

image

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset