Exercise index of this lecture   Alphabetic index   Course home   

Operators, Delegates, and Events

6.1   Interval indexer  

The Interval type represents an oriented interval [from - to] of integers. We use the Interval example to illustrate the overloading of operators. If you have not already done so, read about the idea behind the struct Interval in the course teaching material.

In the client of struct Interval we use an indexer to access elements of the interval. For some interval i, the expression i[0] should access the from-value of i, and i[i.Length-1] should access the to-value of i.

Where, precisely, is the indexer used in the given client class?

Add the indexer to the struct Interval (getter only) which accesses element number j (0 <= j <= i.Length) of an interval i.

Hint: Be careful to take the orientation of the interval into account.

Does it make sense to program a setter of this indexer?



6.2   An interval overlap operation  

In this exercise we continue our work on struct Interval, which we have used to illustrate overloaded operators in C#.

Add an Interal operation that finds the overlap between two intervals. Your starting point should be the struct Interval. In the version of struct Interval, provided as starting point for this exercise, intervals may be empty.

Please analyze the possible overlappings between two intervals. There are several cases that need consideration. The fact that Interval is oriented may turn out to be a complicating factor in the solution. Feel free to ignore the orientation of intervals in your solution to this exercise.

Which kind of operation will you chose for the overlapping operation in C# (method, property, indexer, operator)?

Before you program the operation in C# you should design the signature of the operation.

Program the operation in C#, and test your solution in an Interval client program. You may chose to revise the Interval client program from the teaching material.



6.3   Finding and sorting elements in an array  

In this exercise we will work with searching and sorting in arrays. To be concrete, we work on an array of type Point, where Point is the type we have been programming in earlier exercises.

Via this exercise you are supposed to learn how to pass a delegate to a method such as Find and Sort. The purpose of passing a delegate to Find is to specify which point we are looking for.

Make an array of Point objects. You can, for instance, use this version of class Point. You can also use a version that you wrote as solution to one of the previous exercises.

Use the static method System.Array.Find to locate the first point in the array that satisfies the condition:

The sum of the x and y coordinates is (very close to) zero

The solution involves the programming of an appropriate delegate in C#. The delegate must be a Point predicate: a method that takes a Point as parameter and returns a boolean value.

Next, in this exercise, sort the list of points by use of one of the static Sort methods in System.Array. Take a look at the Sort methods in System.Array. There is an overwhelming amount of these! We will use the one that takes a Comparison delegate, Comparison<T>, as the second parameter. Please find this method in your documentation browser. Why do we need to pass a Comparison predicate to the Sort method?

Comparison<Point> is a delegate that compares two points, say p1 and p2. Pass an actual delegate parameter to Sort in which

   p1 <= p2 if and only if p1.X + p1.Y <= p2.X + p2.Y

Please notice that a comparsion between p1 and p2 must return an integer. A negative integer means that p1 is less than p2. Zero means that p1 is equal to p2. A positive integer means that p1 is greater than p2.

Test run you program. Is your Point array sorted in the way you excepts?



6.4   How local are local variables and formal parameters?  

When we run the following program

using System;
public class Application { 

  public delegate double NumericFunction(double d);   
  static double factor = 4.0;

  public static NumericFunction MakeMultiplier(double factor){
     return delegate(double input){return input * factor;};

  public static void Main(){
    NumericFunction f = MakeMultiplier(3.0); 
    double input = 5.0;

    Console.WriteLine("factor = {0}", factor);
    Console.WriteLine("input = {0}", input);
    Console.WriteLine("f is a generated function which multiplies its input with factor");
    Console.WriteLine("f(input) = input * factor = {0}", f(input));

we get this output

factor = 4
input = 5
f is a generated function which multiplies its input with factor
f(input) = input * factor = 15




6.5   Additional Die events  

In this exercise we add yet another method to the existing event i class Die, and we add another event to Die.

In the Die event example, we have a public event called twoSixesInARow which is triggered if a die shows two sixes in a row. In the sample client program we add an anonymous method to this event which reports the string parameter of the event on standard output.

Add yet another method to the twoSixesInARow event which counts the number of times 'two sixes in a row' appear. For this purpose we need - quite naturally - an integer variable for counting. Where should this variable be located relative to the 'counting method': Will you place the variable inside the new method, inside the Die class, or inside the client class of the Die?

Add a similar event called fullHouse, of the same type Notifier, which is triggered if the Die tosses a full house. A full house means (inspired from the rules of Yahtzee) two tosses of one kind and three tosses of another kind - in a row. For instance, the toss sequence 5 6 5 6 5 leads to a full house. Similarly, the 1 4 4 4 1 leads to a full house. The toss sequence 5 1 6 6 6 6 5 does not contain a full house sequence, and the toss sequence 6 6 6 6 6 is not a full house.

Be sure to test-drive the program and watch for triggering of both events.



Generated: Monday February 7, 2011, 12:16:15