Wednesday, August 23, 2006

C#: Event Model and Observer pattern

Observer pattern can be made easily using C# multicast deletgates. We will define two classes Publisher and Subscriber. Publisher is the class which publish the 'event'. Subscriber class subscribes the event and whenever event is called, subscriber is notified. Subscriber can have function which can be invoked in response to event. This function is called event handler. Publisher-Subscriber model can be built on two methodologies - Pull and Push.
In Pull, subscriber has permission to 'see' data/state of Publisher.
In Push, Publisher notify subscriber with only most relevant data/state. Here I am going to implement Push Model.


//Code
       public class Publisher2
{
// EventHandler delegate is defined .NET as
// public delegate void EventHandler (object obj, EventArgs e);
public event EventHandler onTick;

private void NotifyOnTick(EventArgs e)
{
if (onTick != null)
{
onTick(this, e);
}

}

public void StartClock()
{
int tick = 1;
while (tick <= 10) { System.Threading.Thread.Sleep(1000); NotifyOnTick(new MyEventArgs(tick));
tick++;
}
}

}

public class MyEventArgs : EventArgs
{
private int tick;
public int Tick
{
get { return this.tick;}
}

public MyEventArgs(int tick)
{
this.tick = tick;
}

}

public class Subscriber2
{
private int subsriberID;
public Subscriber2(Publisher2 publisher, int id)
{
this.subsriberID = id;
publisher.onTick += new EventHandler(this.DisplayOnTick);
}
public void DisplayOnTick(object obj, EventArgs e)
{
Console.Write("Subscriber [{0}]: ", this.subsriberID);
MyEventArgs me = e as MyEventArgs;
Console.WriteLine(me.Tick.ToString());
}
public void Unsubscribe(Publisher2 publisher)
{
publisher.onTick -= new EventHandler(this.DisplayOnTick);
}
}


class Class1
{
///
/// The main entry point for the application.
///
[STAThread]
static void Main(string[] args)
{

Publisher2 publisher = new Publisher2();
Subscriber2 sbc1 = new Subscriber2(publisher,1);
Subscriber2 sbc2 = new Subscriber2(publisher,2);
publisher.StartClock();
sbc2.Unsubscribe(publisher);
publisher.StartClock();
}
}
//Output
Subscriber [1]: 1
Subscriber [2]: 1
Subscriber [1]: 2
Subscriber [2]: 2
Subscriber [1]: 3
Subscriber [2]: 3
Subscriber [1]: 4
Subscriber [2]: 4
Subscriber [1]: 5
Subscriber [2]: 5
Subscriber [1]: 6
Subscriber [2]: 6
Subscriber [1]: 7
Subscriber [2]: 7
Subscriber [1]: 8
Subscriber [2]: 8
Subscriber [1]: 9
Subscriber [2]: 9
Subscriber [1]: 10
Subscriber [2]: 10
Subscriber [1]: 1
Subscriber [1]: 2
Subscriber [1]: 3
Subscriber [1]: 4
Subscriber [1]: 5
Subscriber [1]: 6
Subscriber [1]: 7
Subscriber [1]: 8
Subscriber [1]: 9
Subscriber [1]: 10

Tuesday, August 22, 2006

C#: Interface as a subclass of Interface

Following code snippet shows how a Interface can have a Interface as a subclass.

public interface Class1
{
void Display(string str);
}

public interface Class2 : Class1
{
void DisplayInt(int i);
}

public class Class3 : Class2
{
// Must be implemented, even though
// its base class interface doesn't declare this method
public void Display(string str)
{
Console.WriteLine(str);
}
public void DisplayInt(int i)
{
Console.WriteLine(i.ToString());
}
}


public class MyClass
{
public static void Main()
{
Class1 c = new Class3();
//c.DisplayInt(2); // Will work only when Class3 c = new Class3();
c.Display("for tango");
}
}
//ouput
for tango

Casting in C#

In C#, there is two ways to explicitly cast an object:
  1. Using casting operator ()
  2. Using as keyword
Following code snippet conveys 3 important points:
  1. If no constructor is specified in subclass constructor, default constructor of base class is called. So parent class should either have no constructor or should must have default constructor defined if it has other overloaded constructors.
  2. Casting using casting operator throw exception if type is mismatched
  3. Casting using 'as' keyword make object null if type is mismatched
//Code
public class A
{
public A(){Console.WriteLine("Instance of A is created.");}
public A(string str){Console.WriteLine("Instance of A is created with string: " + str);}
}

public class B : A
{
public B(){Console.WriteLine("Instance of B is created.");}
public B(string str)
{
// Automatically calls default constructor
Console.WriteLine("Instance of B is created with string: " + str);
}
}

public class C : B
{
public C(){Console.WriteLine("Instance of C is created.");}
public C(string str) : base(str)
{
// Base Class Constructor B(str) is called
Console.WriteLine("Instance of C is created with string: " + str);
}
}


public class MyClass
{
public static void Main()
{
C c2 = new C("ashish");
A a = new C();
B b = (B) a;// if (ais B) stat.type(a) is Bin this expression; else exception
C c = (C) a;
a = null;
c = (C) a;// ok ..null can be casted to any reference type
A a1 = new A();
//C c1 = (C)a1; // Generates exeception
C c1 = a1 as C;
if (c1 == null) Console.WriteLine ("c1 is null"); // print c1 is null


}
}

// Output of above code
Instance of A is created.
Instance of B is created with string: ashish
Instance of C is created with string: ashish
Instance of A is created.
Instance of B is created.
Instance of C is created.
Instance of A is created.
c1 is null