Search

Categories

Send mail to the author(s) E-mail

# Monday, July 27, 2009
Thanks to:
http://davidhayden.com/blog/dave/archive/2006/05/28/2974.aspx

Anon methods, delegates, predicates.  Anon methods are simple shortcuts so don't have to declare a predicate method.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace TestAnonymousMethods
{
    public class Program
    {
        // using an anon method
        static void Mainx(string[] args)
        {
            int[] _integers = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };

            int[] evenIntegers = Array.FindAll(_integers,
                                        // this is the anonymous method below
                                       delegate(int integer)
                                       {
                                           return (integer % 2 == 0);
                                       }
                );

            foreach (int integer in _integers) 
                Console.WriteLine(integer);

            foreach (int integer in evenIntegers)
                Console.WriteLine(integer);
        }

        // not using anon method
        static void Mainy(string[] args)
        {
            int[] _integers = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };

            // passing in IsEven..a delegate which represents the IsEven method
            int[] evenIntegers = Array.FindAll(_integers, IsEven);

            foreach (int integer in _integers)
                Console.WriteLine(integer);

            foreach (int integer in evenIntegers)
                Console.WriteLine(integer);
        }

        static bool IsEven(int integer)
        {
            return (integer % 2 == 0);
        }


       
        // not using anon method and looking at predicate / delegate of Array.FindAll
        static void Main(string[] args)
        {
            int[] _integers = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
            // a predicate is expected
            // passing in IsEven..a delegate which represents the IsEven method
            int[] whatIsInBoth = Array.FindAll(_integers, IsDaveSequence);

            foreach (int integer in whatIsInBoth)
                Console.WriteLine(integer);

        }

        static bool IsDaveSequence(int integer)
        {
            bool returnState = false;
            if ((integer == 1) || (integer == 3) || (integer ==4))
                returnState = true;
            return returnState;
        }



    }
}

Comments [0] | | # 
# Thursday, April 09, 2009
Why use Events or publish / subscribe?

Any number of classes can be notified when an event is raised.

The subscribing classes do not need to know how the Metronome works, and the Metronome does not need to know what they are going to do in response to the event

The publisher and the subscribers are decoupled by the delegate. This is highly desirable as it makes for more flexible and robust code. The metronome can change how it detects time without breaking any of the subscribing classes. The subscribing classes can change how they respond to time changes without breaking the metronome. The two classes spin independently of one another, which makes for code that is easier to maintain.



Example1 - Metronome
Create a new console app, paste in the Main() code.  Then create 3 new classes (Alt P, C) - Metronome, Listener, ListenerB
A metronome ticks every 2 seconds, and two objects 'hear' it:

class Program
{
    static void Main()
    {
        // setup the metronome and make sure the EventHandler delegate is ready
        Metronome metronome = new Metronome();

        // wires up the metronome_Tick method to the EventHandler delegate
        Listener listener = new Listener(metronome);
        ListenerB listenerB = new ListenerB(metronome);
        metronome.Go();
    }
}

public class Metronome
{
    // a delegate
    // so every time Tick is called, the runtime calls another method
    // in this case Listener.metronome_Tick and ListenerB.metronome_Tick
    public event EventHandler Tick;

    // virtual so can override default behaviour in inherited classes easily
    protected virtual void OnTick(EventArgs e)
    {
        // null guard so if there are no listeners attached it wont throw an exception
        if (Tick != null)
            Tick(this, e);
    }

    public void Go()
    {
        while (true)
        {
            Thread.Sleep(2000);
            // because using EventHandler delegate, need to include the sending object and eventargs 
            // although we are not using them
            OnTick(EventArgs.Empty);
        }
    }
}


public class Listener
{
    public Listener(Metronome metronome)
    {
        metronome.Tick += new EventHandler(metronome_Tick);
    }
    
    private void metronome_Tick(object sender, EventArgs e)
    {
        Console.WriteLine("Heard it");
    }
}

public class ListenerB
{
    public ListenerB(Metronome metronome)
    {
        metronome.Tick += new EventHandler(metronome_Tick);
    }
    
    private void metronome_Tick(object sender, EventArgs e)
    {
        Console.WriteLine("ListenerB: Heard it");
    }
}    
Example2 - MetronomeArgs
We are passing the current time from the Metronome to the 2 listener objects
static void Main()
{
    // setup the metronome and make sure the EventHandler delegate is ready
    Metronome metronome = new Metronome();

    // wires up the metronome_Tick method to the EventHandler delegate
    Listener listener = new Listener(metronome);
    ListenerB listenerB = new ListenerB(metronome);
    metronome.Go();
}

public class Metronome
{
    // a delegate
    // so every time Tick is called, the runtime calls another method
    // in this case Listener.metronome_Tick
    // so objects subscribing to this delegate should look like (object sender, EventArgs e)
    public event EventHandler Tick;
   
    // virtual so can override default behaviour in inherited classes easily
    protected virtual void OnTick(TickEventArgs e)
    {
        // null guard so if there are no listeners attached it wont throw an exception
        if (Tick != null)
            Tick(this, e);
    }

    public void Go()
    {
        while (true)
        {
            Thread.Sleep(2000);
            DateTime now = DateTime.Now;
            TickEventArgs tickEventArgs = new TickEventArgs(now);
            OnTick(tickEventArgs);
        }
    }
}


// Good idea to inherit from EventArgs
// as can upcast EventArgs object in case you need to send it to an event that doesn't handle it???
// sole purpose of EventArgs class (which has no members) is to allow event arguments object to be passed to 
// event handlers
public class TickEventArgs : EventArgs
{
    public DateTime Time { get; private set; }

    public TickEventArgs(DateTime time)
    {
        this.Time = time;
    }
}

public class Listener
{
    public Listener(Metronome metronome)
    {
        metronome.Tick += new EventHandler(metronome_Tick);
    }

    private void metronome_Tick(object sender, EventArgs e)
    {
        // TickEventArgs is a superclass(?) of EventArgs... this is what we passed
        if (e is TickEventArgs)
        {
            // Downcasting e from EventArgs to TickEventArgs so can use its properties
            TickEventArgs tickEventArgs = e as TickEventArgs;
            
            Console.WriteLine("Heard it at time " + tickEventArgs.Time.ToString());
        }
    }
}

public class ListenerB
{
    public ListenerB(Metronome metronome)
    {
        metronome.Tick += new EventHandler(metronome_Tick);
    }
    
    private void metronome_Tick(object sender, EventArgs e)
    {
        Console.WriteLine("ListenerB: Heard it");
        
    }
}
References:
Big thanks on: http://stackoverflow.com/questions/724085/events-naming-convention-and-style
Metronome code is refactored from http://www.codeproject.com/KB/cs/simplesteventexample.aspx
Why use events: http://www.akadia.com/services/dotnet_delegates_and_events.html

Comments [0] | | #