Sie sind auf Seite 1von 8

HaNoi University of Technology

Week 10: Delegates, Events, and Lambdas- C# 2008

Week 10: Delegates, Events, and Lambdas

Goals:

Define a delegate type. Use a delegate to implement a simple callback. Register both instance and static callback methods. Use composition to create a delegate with multiple targets. Use the event keyword to impose well know access semantics on a delegate. Manually invoke the targets of a delegate. Code a delegate with a return value.

Exercise 1
1. Delegates are typically used to implement what design pattern? Singleton Factory method Publish/subscribe 2. What information is specified by a delegate? The types of the objects involved in the registration and callback The name of the callback method The parameter list and return type of the callback method 3. How many subscribers may be registered with a delegate? None - only an event can have registered subscribers One As many as needed 4. A delegate field has what initial value? Zero
null

Empty string 5. What is the effect of adding the event keyword to a delegate field? The delegate is automatically made public Client code is limited to accessing the delegate using only the += and -= operators The delegate is limited to handling only one subscriber

1/8

HaNoi University of Technology

Week 10: Delegates, Events, and Lambdas- C# 2008

Exercise 2
The purpose of this exercise is to illustrate delegates and (quite unrelated, really) the foreach statement. In a new source file TestDelegate.cs, declare a delegate type IntAction that has return type void and takes as argument an int. Declare a static method PrintInt that has return type void and takes a single int argument that it prints on the console. Declare a variable act of type IntAction and assign method PrintInt (as a delegate) to that variable. Call act(42). Declare a method static void Perform(IntAction act, int[] arr) { ... } that applies the delegate act to every element of the array arr. Use the foreach statement to implement method Perform. Make an int array arr and call Perform(PrintInt, arr).

Exercise 3
Create a new source file GenericDelegate.cs and declare a generic delegate type Action<T> that has return type void and takes as argument a T value. This is a generalization of yesterdays delegate type IntAction. Declare a class that has a method static void Perform<T>(Action<T> act, params T[] arr) { ... } This method should apply the delegate act to every element of the array arr. Use the foreach statement when implementing method Perform<T>.

Exercise 4
The purpose of this exercise is to illustrate the use of delegates and especially anonymous method expressions of the form delegate(...) { ... }. Get the file http://www.itu.dk/people/sestoft/csharp/IntList.cs. The file declares some delegate types: public delegate bool IntPredicate(int x); public delegate void IntAction(int x);

2/8

HaNoi University of Technology

Week 10: Delegates, Events, and Lambdas- C# 2008

The file further declares a class IntList that is a subclass of .Nets List<int> class (which is an arraylist; see C# Precisely section 24.4). Class IntList uses the delegate types in two methods that take a delegate as argument: _ list.Act(f) applies delegate f to all elements of list. _ list.Filter(p) creates a new IntList containing those elements x from list for which p(x) is true. Add code to the files Main method that creates an IntList and calls the Act and Filter methods on that list and various anonymous delegate expressions. For instance, if xs is an IntList, you can print all its elements like this: xs.Act(Console.WriteLine); This works because there is an overload of Console.WriteLine that takes an int argument and therefore conforms to the IntAction delegate type. You can use Filter and Act to print only the even list elements (those divisible by 2) like this: xs.Filter(delegate(int x) { return x%2==0; }).Act(Console.WriteLine); Explain what goes on above: How many IntList are there in total, including xs? Further, use anonymous methods to write an expression that prints only those list elements that are greater than or equal to 25. An anonymous method may refer to local variables in the enclosing method. Use this fact and the Act method to compute the sum of an IntLists elements (without writing any loops yourself). Note: If you have an urge to make this exercise more complicated and exciting, you could declare a generic subclass MyList<T> of List<T> instead of IntList, and make everything work for generic lists instead of just IntLists. You need generic delegate types Predicate<T> and Action<T>, but in fact these are already declared in the .Net System namespace.

Exercise 5
Answer the following questions about the Lambda Calculus: a. Is it possible to write a compiler that will generate code just for programs that terminate? Justify

b. Is it possible to implement any algorithm in Haskell? Justify your answer

3/8

HaNoi University of Technology

Week 10: Delegates, Events, and Lambdas- C# 2008

c. Why is normal order evaluation called lazy?

d. What is name capture and how does the Lambda Calculus avoid it? Answer:

e. How can name capture occur in a programming language? Answer:

f. Is it possible to model real numbers? Justify your answer. Answer:

Exercise 6
Consider the following -expressions. Indicate which occurrences of variables are bound and which ones are free in the expressions. The goal of this exercise is to represent some terms of the Lambda Calculus in Haskell. A file called HaskellDataType.hs is available at the PL website. It contains basic type definitions used for the Lambda Calculus. Using these definitions, implement the following functions in Haskell and indicate the type for each function. a. eqLambda, which takes two Lambda expressions as parameters and tests if they are equal. b. freeVars, which takes a Lambda expression as parameter and returns a list of its free variables. c. substitution, which takes two Lambda expressions and a variable as parameters, and returns a new Lambda expression where each occurrence of the variable within the first Lambda

4/8

HaNoi University of Technology

Week 10: Delegates, Events, and Lambdas- C# 2008

expression is substituted by the second Lambda expression (if possible, define the substitution according to the rules given in the theoretical part of the lecture). d. betaA, which takes a Lambda expression as parameter and returns the reduced Lambda expres-sion by applying a -reduction in applicative order. e. betaN, which takes a Lambda expression as parameter and returns the reduced Lambda expres-sion by applying a -reduction in normal order Remark: The file HaskellDataType.hs will not compile immediately. To compile it, you have to define the function eqLambda asked in this exercise.

Exercise 7
Invocation List (optional) A delegate can have multiple targets. Invoking the delegate invokes all the registered targets. This automatic invocation is typically convenient and desirable; however, there are a few cases where more control is required. Suppose a target were to throw an exception. The default behavior is to stop processing the targets and propagate the exception to the publisher. The publisher might prefer to invoke each target individually, catch any exception that is thrown, and continue the processing of the remaining targets. Another case to consider is a delegate with a return type other than void. The default behavior is to return the result from the last target in the sequence and discard the others. The publisher might prefer to obtain the result from each target. To allow a publisher more control over target invocation, delegates offer a GetInvocationList method that returns the individual targets. The targets are returned as an array of delegates - each element in the array represents one target. The publisher can iterate through the array and invoke each target individually. In this lab, we recode the Publisher class Dispatch method from the last exercise so it manually invokes each target. In the PublisherDispatch method, remove the invocation of the delegate. In its place, retrieve the invocation list from the delegate, step through the array, and invoke each target individually.

5/8

HaNoi University of Technology

Week 10: Delegates, Events, and Lambdas- C# 2008

Notes:
o

o o

The type of each array element is the system type Delegate; however, the array is actually filled with MessageHandler objects. As you step through the array, downcast each element of the array to MessageHandler. Use standard method call syntax to invoke the individual targets after the downcast. A foreach loop is probably the simplest way to accomplish the goal here since it will both step through the array and downcast each element.

6/8

HaNoi University of Technology

Week 10: Delegates, Events, and Lambdas- C# 2008

7/8

HaNoi University of Technology

Week 10: Delegates, Events, and Lambdas- C# 2008

8/8