Delegates and Events – Part 1.

This topic is quite interesting for beginners too. You can often face the usage of delegates and of course: events.

Delegates

If you want to execute an action but you don’t know which method or object you’ll want to call upon to execute it. For example, you want to play some media files with the help of an object but you don’t know what object will be playing the file and what file should be played: video, audio, animation, etc. You would create a delegate and the resolve that delegate to a method when the program executes.

Delegates are reference types but they are referring to a method and not to an object. This is called encapsulating the method.
You will need to create a method signature and return type when you create a delegate. Of course you can encapsulate any matching method with that delegate.

Let’s create out first delegate:

public delegate int GetResultId(object o1, object o2);

This delegate can encapsulate any method that takes two objects as parameters and return witn an integer.

Now let’s create a new console or winform application. We will create 3 new classes. It’s up to you either you create these classes in separate files or under your main class.

First class:

    public class MyMedia
    {
        public delegate int PlayMyMedia();

        public void ShowResult(PlayMyMedia playerDelegate)
        {
            if (playerDelegate() == 0)
            {
                Console.WriteLine(@"Music played successfully");
            }
            else
            {
                Console.WriteLine(@"Music error");
            }
        }
    }

This class has the delegate declared and a normal method with one interesting thing: the input parameter is not an integer as may be expected, but a delegate with the type of PlayMyMedia. This delegate can encapsulate any method that has no input parameter and returns with an integer.

Now let’s create our music class:

    public class MusicPlayer
    {
        private int _playerStatus;

        public int Play()
        {
            Console.WriteLine(@"Playing music...");
            _playerStatus = 0;
            return _playerStatus;
        }
    }

You can see the this Play method has the same signature as the delegate (no input parameters and return type of integer), so it can be used with our delegate.

Create a similar class to this music class:

    public class VideoPlayer
    {
        private int _playerStatus;

        public int Play()
        {
            Console.WriteLine(@"Playing video...");
            _playerStatus = 1;
            return _playerStatus;
        }
    }

Same here: the only method can be called with the delegate. The name of the method (Play) can be anything you like. You can use PlayAudioFile in MusicPlayer class and PlayVideoFile in VideoPlayer class.

This was the easy part. Now we have to instantiate MyMedia class, both player classes, the delegate and call the ShowResult() method. Let’s do this in a new class, called Tester:

    public class Tester
    {
        public void Run()
        {
            MyMedia myMedia = new MyMedia();

            MusicPlayer mymusicPlayer = new MusicPlayer();
            VideoPlayer myVideoPlayer = new VideoPlayer();

            MyMedia.PlayMyMedia audioPlayerDelegate = new MyMedia.PlayMyMedia(mymusicPlayer.Play);
            MyMedia.PlayMyMedia videoPlayerDelegate = myVideoPlayer.Play;//the same initialization as audioPlayerDelegate above

            myMedia.ShowResult(audioPlayerDelegate);
            myMedia.ShowResult(videoPlayerDelegate);
        }
    }

To instantiate a delegate you have to use the new keyword, but you have to pass a method as a parameter.

Delegates are the type of the parent class, that’s why you should use MyMedia.PlayMyMedia type when instantiating a new delegate.

Now you have the references to the Play methods with 2 delegates with type of PlayMyMedia. Both initialization is ok, but the first one (with the new keyword) is the obsolete version: use the second one.

Calling the ShowResult method first time with parameter of the delegate causes to call the Play() method in MusicPlayer class, the second time the Play() method in the VideoPlayer class. At compile time ShowResult() method doesn’t know which method is going to call, only when it’s invoked at runtime.

Now let’s try it. If you created a console application, then write the following two lines in your Main method:

        Tester t = new Tester();
        t.Run();

Using winform application, write it after InitializeComponent() or anywhere you like.