Call Events with Delegate in C#

Scenario: Call method of 2nd Class while calling method of 1st Class using delegates.
                       “Call friends when employee get promoted”

Example:
    delegate void PromoteDelegate(string eName);
    class Program
    {
        //PM
        static void Main(string[] args)
        {
            Friend f = new Friend();
            Employee e = new Employee();
            e.pd += new PromoteDelegate(f.CallWhenPromoted);
            e.Promoted("Mehul");

            //e.pd();
            Console.ReadLine();
        }
    }

    class Employee
    {
        public event PromoteDelegate pd;
        public void Promoted(string eName)
        {
            Console.WriteLine("Congratulation! Employee {0} 
            get promoted...",eName);
            Console.WriteLine("Calling Delegate...");
            pd("Mehul's friend");
        }
    }

    class Friend
    {
        public void CallWhenPromoted(string fName)
        {
            Console.WriteLine("Thanks for calling {0}...", fName);
        }
    }
  
Output:
            Congratulation! Employee Mehul get promoted...
            Calling Delegate...
            Thanks for calling Mehul's friend...

Extension Methods in C#


Extension methods allow you to extend an existing type with new functionality, without having to sub-class or recompile the old type.

Key Points:
         1: Extension Class must be static
         2: Extension Method must be static
         3: 1st Param in extension method must contains type which are geting extended    

Example:
    class Program
    {
        static void Main(string[] args)
        {
            //Default String
            String str = "My Name is XYZ";

            //LINQ Query to get count of vowels (use of Extension method)
            var queryChar = from ch in str.ToUpper()
                        where ch.IsVowel()
                        select ch;
            //Display result
            Console.WriteLine("Calling Char Extension Method:");
            Console.WriteLine("String \"{0}\" contains {1} Vowels", str, 
            queryChar.Count());
            Console.WriteLine();

            //Count Words in string (use of Extension method)
            int countWords = str.CountWords();
            Console.WriteLine("Calling String Extension Method:");
            Console.WriteLine("String \"{0}\" contains {1} Words", str, 
            countWords);
            Console.WriteLine();

            //Get Factorial from given integer  (use of Extension method)
            Console.WriteLine("Enter an integer to get factorial");
            int i =  int.Parse(Console.ReadLine());
            Console.WriteLine("Calling Int Extension Method:");
            Console.WriteLine("Factorial of {0} is: {1}", i, i.GetFactorial());

            Console.ReadLine();           
        }
    }

    /*Creating Extension Method*/
    static class Exten
    {
        public static bool IsVowel(this char ch)
        {
            return "AEIOU".Contains(ch);
        }

        public static int CountWords(this string str)
        {
            return str.Split(new char[] { ' ', '.', '?' },
                             StringSplitOptions.RemoveEmptyEntries).Length;
        }
        public static Int64 GetFactorial(this int x)
        {
            if (x <= 1) return 1;
            if (x == 2) return 2;
            else
                return x * GetFactorial(x - 1);
        }
    }

Output:
Calling Char Extension Method:
String "My Name is XYZ" contains 3 Vowels

Calling String Extension Method:
String "My Name is XYZ" contains 4 Words

Enter an integer to get factorial
8
Calling Int Extension Method:
Factorial of 8 is: 40320

Delegate in C#

What is a Delegate?
A delegate is a type that references a method. Once a delegate is assigned a method, it behaves exactly like that method. The delegate method can be used like any other method, with parameters and a return value.

Declaration:
             public delegate returntype_of_delegate delegate_name();

Important Points:
•         Delegates are similar to C++ function pointers, but are type safe.
•         Delegates allow methods to be passed as parameters.
•         Delegates can be used to define callback methods.
•         Delegates can be chained together; for example, multiple methods can be called on a single event.
•         You can use delegates without parameters or with parameter list
•         You should follow the same syntax as in the method
(If you are referring to the method with two int parameters and int return type, the delegate which you are declaring should be in the same format. This is why it is referred to as type safe function pointer.)

Basic Example:
    //[a.m]delegate returntype DelegateName(Pl);
    delegate int MyDel(int a, int b);
    class Program
    {
        static void Main(string[] args)
        {
            SimpleMath sm = new SimpleMath();
            //MyDel md1 = new MyDel(SimpleMath.Sub);
            //MyDel md2 = new MyDel(sm.Add);
            //MyDel md3 = md1 + md2;
            MyDel md = new MyDel(SimpleMath.Sub);
            md += new MyDel(SimpleMath.Add);
            //Console.WriteLine(md(20,10));

            Delegate[] dels = md.GetInvocationList();
            foreach (Delegate item in dels)
            {
                Console.WriteLine();
                object[] obj = { 20, 10 };
                Console.WriteLine("Delegate for method {0} called; Result: {1}",                            item.Method.Name, item.Method.Invoke(null, obj));
            }
            Console.ReadLine();
        }
    }
    class SimpleMath
    {
        public static int Add(int num1, int num2)
        {
            return num1 + num2;
        }
        public static int Sub(int num1, int num2)
        {
            return num1 - num2;
        }
    }

Output:
Delegate for method Sub called; Result: 10
Delegate for method Add called; Result: 30

Example Combine Delegates:
delegate void Del(string s);
        class TestClass
        {
            static void Hello(string s)
            {
                System.Console.WriteLine("  Hello, {0}!", s);
            }

            static void Goodbye(string s)
            {
                System.Console.WriteLine("  Goodbye, {0}!", s);
            }

            static void Main()
            {
                Del a, b, c, d;

                // Create the delegate object a that references
                // the method Hello:
                a = Hello;

                // Create the delegate object b that references
                // the method Goodbye:
                b = Goodbye;

                // The two delegates, a and b, are composed to form c:
                c = a + b;

                // Remove a from the composed delegate, leaving d,
                // which calls only the method Goodbye:
                d = c - a;

                System.Console.WriteLine("Invoking delegate a:");
                a("A");
                System.Console.WriteLine("Invoking delegate b:");
                b("B");
                System.Console.WriteLine("Invoking delegate c:");
                c("C");
                System.Console.WriteLine("Invoking delegate d:");
                d("D");
            }
        }

Output:
Invoking delegate a:
  Hello, A!
Invoking delegate b:
  Goodbye, B!
Invoking delegate c:
  Hello, C!
  Goodbye, C!
Invoking delegate d:
  Goodbye, D!