Tuesday, February 9, 2010

INHERITANCE


INHERITANCE 
Inheritance
The concept of inheritance brings something of a real-world view to programming. It allows a class to be defined which has a number of characteristics and then other classes to be created which are derived from that class. The derived class inherits all of the features of the parent class and typically then adds some features of its own.
By deriving classes we create what is often referred to as a class hierarchy. The class at the top of the hierarchy is known as the base class and the derived classes as subclasses. Any number of classes may be derived from a class. It is only possible for a derived class to inherit from one class. As such, C# is known as a single inheritance programming language.
Classes need not only be derived from a base class. For example, a subclass can also inherit from another subclass.
An Example of Inheritance
As with most programming concepts the subject of inheritance in C# is perhaps best illustrated with an example. In the previous chapter we created a class called BankAccount:
public class BankAccount
{

        public string accountName;
        public int accountFee;
        private int accountBalance;
        private int accountNumber;

        public int getAccountNumber()
        {
               return accountNumber;
        }

        public void setAccountNumber(int newNumber)
        {
               accountNumber = newNumber;
        }

}
This class does a good job of defining characteristics common to any type of bank account, such as account holder name, account number and current balance. Imagine, however, that our banking program needs to support a number of specific types of account. For example, the bank might offer its customers an interest bearing savings account. A savings account will have all the characteristics of our BankAccount class but would also need a way to store the prevailing interest rate. One option would be to create a brand new class from the ground up called SavingsAccount which duplicates everything we have in our BankAccount class, plus extra members needed for a savings account. Another, more efficient method is to derive a SavingsAccount class from the BankAccount class and then add in the extra functionality into this subclass.
Creating a Subclass in C#
Now that we have ascertained that we need to create a sub class of our BankAccount class we can take a look at the code necessary to achieve this. Subclasses are declared in the same way as any other class with the exception that the class name is followed by a colon (:) followed by the name of the class from which it is to inherit. With this in mind we can begin by creating our SavingsAccount class:
public class BankAccount
{

        public string accountName;
        public int accountBalance;
        public int accountNumber;

        public BankAccount (string name, int number)
        {
               accountName = name;
               accountNumber = number;
        }

        public int getAccountNumber()
        {
               return accountNumber;
        }

        public void setAccountNumber(int newNumber)
        {
               accountNumber = newNumber;
        }

}

public class SavingsAccount : BankAccount
{
}
We have now created a sub class of BankAccount called SavingsAccount, but at this point the SavingsAccount class is no different than its parent class. Next we need to add some new members to add the behavior we need:
public class SavingsAccount : BankAccount
{
        public double interestRate;

        public SavingsAccount (string name, int number, int balance, double rate)
               : base (name, number)
        {
               accountBalance = balance;
               interestRate = rate;
        }

        public double monthlyInterest()
        {
               return interestRate * accountBalance;
        }
}
We now have a new class called SavingsAccount which inherits all the members of the BankAccount class and adds some members of its own. In particular we have added a new data member called interestRate which will store the interest rate paid on the account together with a new method to calculate the monthly interest.
Passing Arguments to the Base Class Constructor
Of particular significance is the constructor. In the BankAccount base class we have a constructor which takes the account name and account number as arguments. In the SavingsAccount subclass we need to accept two additional arguments - the balance and the interest rate. The : base code instructs C# to handle the name and number arguments using the constructor from the base class. The remaining two arguments are then passed to the SavingsAccount constructor.
With our subclass complete we can now make use of it:
       static void Main()
        {
          SavingsAccount saveAccount = new SavingsAccount("Aditya Tyagi", 123456, 432, 0.02F);

          Console.WriteLine ("Interest this Month = " + saveAccount.monthlyInterest() );
        }









Wednesday, January 6, 2010

Anonymous Methods


Anonymous Methods
In the original C# language, to construct a delegate object you have to provide it with the name of a method. The code below shows an example: ‘Print’ is first defined as a particular delegate type, then its instance ‘delegateVariable’ is created by passing it the name of the method ‘realMethod’.
1.
delegate void Print (string s);
2.
Print delegateVariable = new Print(realMethod);
3.
4.
public void realMethod (string myString)
5.
{
6.
    MessageBox.Show(myString);
7.
}

Now, however, C# has been updated to include ‘anonymous’ methods (which should be pretty easy for anyone who has used anonymous functions in languages like Javascript). These allow you to construct a delegate by specifying, rather than just naming a method. The following gives an example of how the above code could be written using an anonymous method:
1.
public delegate void Print (string s);
2.
Print delegateVariable = delegate(string myString) {MessageBox.Show(myString);};

In the above case, the anonymous method is given the same signature as the delegate it is passed to. But this is not always necessary. For the anonymous method to be acceptable, the following two conditions must be met:
1. Either the anonymous method has a parameter list that exactly matches the delegate’s parameters; or the anonymous method has no parameter list and the delegate has no ‘out’ parameters.
2. Either the values returned by the anonymous method are all of the right type for the delegate; or the anonymous method doesn’t return anything and the delegate’s return type is ‘void’.
An implication of the first condition is that an anonymous method with no parameters at all can fit a delegate with parameters. The following code is thus possible (notice that we’ve had to remove the use of ‘myString’ in the Show method, because we’re no longer passing it in):
1.
public delegate void Print (string s);
2.
Print delegateVariable = delegate {MessageBox.Show(“hello world!”);};

Anonymous methods can also make use of the local variables and parameters in whose scope the anonymous method lies. This is a somewhat complicated, and we don’t yet have a clear idea of when one should exploit it. So to illustrate it we’ll borrow the example from the documentation.
1.
delegate int myDelegate();
2.
class Test
3.
{
4.
    static myDelegate myFunc()
5.
    {
6.
        int x=0;
7.
        myDelegate result = delegate {return ++x;}
8.
        return result;
9.
    }
10.
    
11.
    static void Main()
12.
    {
13.
        myDelegate d = myFunc();
14.
        Console.WriteLine(d());
15.
        Console.WriteLine(d());
16.
        Console.WriteLine(d());
17.
    }
18.
}

Here the delegate ‘result’ declared in the function ‘myFunc’ makes use of (in the jargon, captures) the integer ‘x’ which is declared in the same function. Now, if we run the code, the output is this:
1
2
3
This result is somewhat surprising, since the integer ‘x’ is instantiated and its value maintained across three delegate calls after the function myFunc has finished running. How this is described in the documentation is that the lifetime of the captured outer type is ‘extended’, so that it lasts as long as any delegate that references it.
A further point to note is that in the example above each delegate is clearly referencing the same type instance. But there are situations in which local variables get initialized many times within a function, and these variables will count as different type instances. For example, in the following loop, the integer i is initialised three times, and the delegates added into the myDelegateArray will reference different variables.
1.
myDelegate[] myDelegateArray = new myDelegate[3];
2.
for (int x=0; x<3; x++)
3.
{
4.
    int i = x;
5.
    myDelegateArray[x] = delegate {return ++i};
6.
}

One question that this naturally raises is whether the multiple initialisation of i gives a performance hit, which one could avoid by declaring i outside the loop. But the documentation suggests that this isn’t the case; each new instance of i just slots neatly into the place vacated by the previous one.

Thursday, December 17, 2009

Events


Events

To recap: in object-oriented languages, objects expose encapsulated functions called methods. Methods are encapsulated functions which run when they are invoked.
Sometimes, however, we think of the process of method invocation more grandly. In such a case, the method invocation is termed an 'event', and the running of the method is the 'handling' of the event. An archetypal example of an event is a user's selection of a button on a graphical user interface; this action may trigger a number of methods to 'handle' it.
What distinguishes events from other method invocations is not, however, that they must be generated externally. Any internal change in the state of a program can be used as an event. Rather, what distinguishes events is that they are backed by a particular 'subscription-notification' model. An arbitrary class must be able to 'subscribe to' (or declare its interest in) a particular event, and then receive a 'notification' (ie. have one of its methods run) whenever the event occurs.
Delegates - in particular multicast delegates - are essential in realizing this subscription-notification model. The following example describes how Class 2 subscribes to an event issued by Class 1.
1. Class 1 is an issuer of E-events. It maintains a public multicast delegate D.
2. Class 2 wants to respond to E-events with its event-handling method M. It therefore adds onto D a reference to M.
3. When Class 1 wants to issue an E-event, it calls D. This invokes all of the methods which have subscribed to the event, including M.
The 'event' keyword is used to declare a particular multicast delegate (in fact, it is usual in the literature to just identify the event with this delegate). The code below shows a class EventIssuer, which maintains an event field myEvent. We could instead have declared the event to be a property instead of a field  . To raise the myEvent event, the method onMyEvent is called (note that we are checking in this method to see if myEvent is null - trying to trigger a null event gives a run-time error).
1.
public class EventIssuer
2.
{
3.
    public delegate void EventDelegate(object from, EventArgs args);
4.
    public event EventDelegate myEvent;
5.
6.
    protected virtual void onMyEvent(EventArgs args)
7.
    {
8.
        if (myEvent!=null)
9.
            myEvent(this, args);
10.
    }
11.

A class which wanted to handle the events issued by an EventIssuer ei with its method handleEvents would then subscribe to these events with the code:
ei.myEvent += new EventIssuer.EventDelegate(handleEvents);

Good Practice For Events

The code above demonstrates some points about event-handling which are not enforced by the language architecture, but are used throughout the .Net framework as good practice.
1. When you want to raise an event in code, you don't tend to trigger the class's event object directly. Rather, you call a 'protected, virtual' method to trigger it (cf. the onMyEvent method above).
2. By convention, when events are raised they pass two objects to their subscribers. The first is a reference to the class raising the event; the second is an instance of the System.EventArgs class which contains any arbitrary data about the event.
3. If an event is not interested in passing data to subscribers, then its defining delegate will still reference an EventArgs object (but a null value will be passed by the event). If an event should pass data to its subscribers, however, then it is standard to use a specific class which derives from the EventArgs class to hold this data.
4. When you write a class which inherits from an event-raising base class, you can 'intercept' an event by overriding the method used to raise it. The following code illustrates such an intercept - classes which subscribe to the event will never receive notifications about it.
1.
    protected override void onMyEvent(EventArgs args)
2.
    {
3.
         Console.WriteLine("hello");
4.
    }
5.

If you want subscribers to continue to receive notifications despite such an 'intercepting' method, however, then you can call the base class method as in the following:
1.
    protected override void onMyEvent(EventArgs args)
2.
    {
3.
         Console.WriteLine("hello");
4.
         base.onMyEvent(args);
5.
    }
6.




DELEGATE



Delegates are reference types which allow indirect calls to methods. A delegate instance holds references to some number of methods, and by invoking the delegate one causes all of these methods to be called. The usefulness of delegates lies in the fact that the functions which invoke them are blind to the underlying methods they thereby cause to run (see, for instance, the discussion of events, below).
From this brief description, it can be seen that delegates are functionally rather similar to C++'s 'function pointers'. However, it is important to bear in mind two main differences. Firstly, delegates are reference types rather than value types. Secondly, some single delegates can reference multiple methods

Delegate Declaration and Instantiation

Delegates can be specified on their own in a namespace, or else can be specified within another class (the examples below all show the latter). In each case, the declaration specifies a new class, which inherits from System.MulticastDelegate.
Each delegate is limited to referencing methods of a particular kind only. The type is indicated by the delegate declaration - the input parameters and return type given in the delegate declaration must be shared by the methods its delegate instances reference. To illustrate this: a delegate specified as below can be used to refer only to methods which have a single String input and no return value:
public delegate void Print (String s);
Suppose, for instance, that a class contains the following method:
1.
public void realMethod (String myString)
2.
{
3.
    // method code
4.
}

Another method in this class could then instantiate the 'Print' delegate in the following way, so that it holds a reference to 'realMethod':
Print delegateVariable = new Print(realMethod);
We can note two important points about this example. Firstly, the unqualified method passed to the delegate constructor is implicitly recognised as a method of the instance passing it. That is, the code is equivalent to:
Print delegateVariable = new Print(this.realMethod);
We can, however, in the same way pass to the delegate constructor the methods of other class instances, or even static class methods. In the case of the former, the instance must exist at the time the method reference is passed. In the case of the latter (exemplified below), the class need never be instantiated.
Print delegateVariable = new Print(ExampleClass.exampleMethod);
The second thing to note about the example is that all delegates can be constructed in this fashion, to create a delegate instance which refers to a single method. However, as we noted before, some delegates - termed 'multicast delegates' - can simultaneously reference multiple methods. These delegates must - like our Print delegate - specify a 'void' return type.
One manipulates the references of multicast delegates by using addition and subtraction operators (although delegates are in fact immutable reference types ) The following code gives some examples:
1.
Print s = null;
2.
s = s + new Print (realMethod);
3.
s += new Print (otherRealMethod);

The - and -= operators are used in the same way to remove method references from a delegate.
The following code gives an example of the use of delegates. In the Main method, the Print delegate is instantiated twice, taking different methods. These Print delegates are then passed to the Display method, which by invoking the Print delegate causes the method it holds to run. As an exercise, you could try rewriting the code to make Print a multicast delegate.
1.
using System;
2.
using System.IO;
3.
4.
public class DelegateTest
5.
{
6.
    public delegate void Print (String s);
7.
8.
    public static void Main()
9.
    {
10.
        Print s = new Print (toConsole);
11.
        Print v = new Print (toFile);
12.
        Display (s);
13.
        Display (v);
14.
    }
15.
16.
    public static void toConsole (String str)
17.
    {
18.
        Console.WriteLine(str);
19.
    }
20.
21.
    public static void toFile (String s)
22.
    {
23.
        StreamWriter fileOut = File.CreateText("fred.txt");
24.
        fileOut.WriteLine(s);
25.
        fileOut.Flush();
26.
        fileOut.Close();
27.
    }
28.
29.
    public static void Display(Print pMethod)
30.
    {
31.
        pMethod("This should be displayed in the console");
32.
    }
33.
}