Exercise index of this lecture   Alphabetic index   Course home   

Exercises and solutions
Data Access, Properties, and Methods


5.1   A funny BankAccount  

In this exercises we provide a version of class BankAccount with a "funny version" of the Balance property. You should access the exercise via the web version, in order to get access to the source programs involved.

Study the Balance property of the funny version of class BankAccount.

Explain the behaviour of the given client of the funny BankAccount.

Next test-run the program and confirm your understanding of the two classes.

Please notice how difficult it is to follow the details when properties - like Balance in the given version of class BankAccount - do not pass data directly to and from the instance variables.

Solution

The following output appears when I run the program:

Peter's account holds 1000 kroner
Balance = 2000
Peter's account holds 1000 kroner
Peter's account holds 2050 kroner

The expression ba.Balance returns twice the actual balance of the account: 2000.

The assignment

   ba.Balance += 100;

is equivalent to

   ba.Balance = Ba.Balance + 100;

The value of the expression

   Ba.Balance + 100

is 2100. When the setter of Balance is applied, 2100 - 50 = 2050 is assigned to the instance variable balance.


5.2   Point setters  

In the Point class on the accompanying slide we have shown how to program getter properties in the class Point. Extend the four properties with setters as well. The new version of this class will support mutable points.

Write a small client program that demonstrates the use of the setter properties.

Hint: Please be aware that the revised class should allow us to get and set the rectangular and polar coordinates (x, y, angle, radius) of a point independent of each other. You should first consider what it means to do so.

Solution

Please consult the for setters of the properties x, y, r, and a below:

using System;

public class Point {

  // Polar representation of points:
  private double radius, angle;            // radius, angle

  public enum PointRepresentation {Polar, Rectangular}

  // Point constructor:
  public Point(PointRepresentation pr, double n1, double n2){
    if (pr == PointRepresentation.Polar){
      radius = n1; angle = n2;
    } 
    else if (pr == PointRepresentation.Rectangular){
      radius = RadiusGivenXy(n1, n2);
      angle  = AngleGivenXy(n1, n2);
    } else {
      throw new Exception("Should not happen");
    }
  }   

  public double x {
    get {
      return XGivenRadiusAngle(radius, angle);}
    set {
      double yBefore = YGivenRadiusAngle(radius, angle);
      angle = AngleGivenXy(value, yBefore);
      radius = RadiusGivenXy(value, yBefore);
    }
  }   

  public double y {
    get {
      return YGivenRadiusAngle(radius, angle);}
    set {
      double xBefore = XGivenRadiusAngle(radius, angle);
      angle = AngleGivenXy(xBefore, value);
      radius = RadiusGivenXy(xBefore, value);
    }
  }   

  public double r {
    get {
     return radius;}
    set {
     radius = value;}
  }   

  public double a {
    get {
     return angle;}
    set {
     angle = value;}
  }   

  public void Move(double dx, double dy){
    x += dx;  y += dy;
  }

  public void Rotate(double angle){
    a += angle;
  }

  public override string ToString(){
    return  "(" + x + "," + y + ")" + " " +  "[r:" + r + ", a:" + a + "]  ";
  }

  protected static double RadiusGivenXy(double x, double y){
    return Math.Sqrt(x * x + y * y);
  }

  protected static double AngleGivenXy(double x, double y){
    return Math.Atan2(y,x);
  }

  protected static double XGivenRadiusAngle(double r, double a){
    return r * Math.Cos(a);
  }

  protected static double YGivenRadiusAngle(double r, double a){
    return r * Math.Sin(a);
  }


}


5.3   Passing references as ref parameters  

In the Date and Person classes of the corresponding slide we pass a reference as a value parameter to method DayDifference in class Date. Be sure to understand this. Read about ref parameters later in this lecture.

Assume in this exercise that the formal parameter other in Date.DayDifference is passed by reference (as a C# ref parameter). Similarly, the actual parameter dateOfBirth to DayDifference should (of course) be passed by reference (using the keyword ref in front of the actual parameter).

What will be the difference caused by this program modification.

Test-drive the program with a suitable client to verify your answer.

Solution

The C# ref parameter other in the method DayDifference will be an alternative name of the private instance variable dateOfBirth in an object of class Person. The year of this date of birth is incremented. This is the same effect as with the call-by-value parameter.

If the parameter other is a ref parameter it is important to notice what happens, if we assign to this parameter. We do not, however, in the concrete program. If we did, we could arrange that the private instance variable dateOfBirth in the Person object becomes a reference to a new Date.

Here is a tabular overview of the two exercises and the programs on the corresponding slides:

class struct
by value Like call by reference in C. The parameter other is a reference to another date. We can mutate this date, but we cannot change the value of the actual parameter dateOfBirth by assigning to other.

The birthday can be mutated.

A struct dateOfBirth is copied to other. The year of the copied Date is changed. It does not affect the dateOfBirth. This is pure value semantics. Value types (structs) and call by value fit nicely together.

The birthday is protected from mutation.

by C# ref The formal parameter other becomes an alias of the actual parameter dateOfBirth. We can therefore mutate this date, as above. If we assign to other we do, in reality, assign to dateOfBirth. This observation is the real difference between this case and the case above.

The birthday can be mutated.

As above, the formal parameter other becomes an alias of the actual parameter dateOfBirth. If we mutate the year of other, we change the year of dateOfBirth. If we assign to other we will (by copying and value semantics) change the dateOfBirth.

The birthday can be mutated.


5.4   Passing struct values as ref parameters  

This exercise corresponds to the similar exercise on the previous slide.

In the Date struct and the Person class of this slide we pass a struct value as a value parameter to the method DayDifference.

Assume in this exercise that the formal parameter other in Date.DayDifference is passed by reference (a C# ref parameter). Similarly, the actual parameter dateOfBirth to DayDifference should (of course) be passed by reference (using the keyword ref in front of the actual parameter).

What will be the difference caused by this program modification. You should compare with the version on on the slide.

Test-drive the program with a suitable client to verify your answer.

Solution

The reference parameter other in DayDifference will be an alternative name of the private instance variable dateOfBirth in a Person object. Thus, the ref parameter other is not a copy of actual parameter. other is an alias of the actual parameter. Thus, the year of dateOfBirth is incremented. We see that this is NOT the same effect as with the call by value parameter on the slide.

In the version on the slide the copy of Date in other is a local copy. It has no effect on the surrounding of DayDifference if we mutate the year of other.

Here is a tabular overview of the two exercises and the programs on the corresponding slides:

class struct
by value Like call by reference in C. The parameter other is a reference to another date. We can mutate this date, but we cannot change the value of the actual parameter dateOfBirth by assigning to other.

The birthday can be mutated.

A struct dateOfBirth is copied to other. The year of the copied Date is changed. It does not affect the dateOfBirth. This is pure value semantics. Value types (structs) and call by value fit nicely together.

The birthday is protected from mutation.

by C# ref The formal parameter other becomes an alias of the actual parameter dateOfBirth. We can therefore mutate this date, as above. If we assign to other we do, in reality, assign to dateOfBirth. This observation is the real difference between this case and the case above.

The birthday can be mutated.

As above, the formal parameter other becomes an alias of the actual parameter dateOfBirth. If we mutate the year of other, we change the year of dateOfBirth. If we assign to other we will (by copying and value semantics) change the dateOfBirth.

The birthday can be mutated.


5.5   Extending struct Double  

At the accompanying page we have seen how class Point can be extended with the instance method DistanceTo. This is an extension method.

If you study the method DistanceTo you will see that we use the squareroot function Math.Sqrt, defined statically in class Math. And we could/should have used a similar Square function had it been available.

It is remarkable that C# 3.0 allows us to extend the structs behind the primitive types, such as Double and Int32.

Write a static class that extends struct Double with the two extension methods Sqrt and Square. Afterwards, rewrite the method DistanceTo such that it makes use of the new instance methods in struct Double.

Solution

Here is the class DoubleExtensions which defines the methods Square and Sqrt:

using System;

public static class DoubleExtensions{

  public static double Square(this Double d){
    return d * d;
  }

  public static double Sqrt(this Double d){
    return Math.Sqrt(d);
  }

}

The extension methods can be called in the following ways in the method DistanceTo in class PointExtensions:

using System;

public static class PointExtensions{

  public static double DistanceTo(this Point p1, Point p2){

    return ((p1.X - p2.X).Square() + (p1.Y - p2.Y).Square()).Sqrt();

  }

}

Do you like the idea of calling numeric functions, such as Square as n.Square() instead of Square(n)?


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