Generics and Delegates

   
 

using System;

public delegate void DelegateClass(int data);

public class Starter {
    public static void Main() {
        DelegateClass del1 = MethodA<int>;
        del1(5);
        DelegateClass del2 = MethodA;
        del1(10); // inferred
    }
    public static void MethodA<T>(T data) {
        Console.WriteLine("MethodA ({0})", data);
    }
}

    


Generic Delegate and non-generic delegate

   
 

using System;
using System.Collections.Generic;
using System.Text;

public delegate void MyGenericDelegate<T>(T arg);

public delegate void MyDelegate(object arg);

class Program {
    static void Main(string[] args) {
        MyDelegate d = new MyDelegate(MyTarget);
        d("More string data");
        MyDelegate d2 = new MyDelegate(MyTarget);
        d2(9);

        MyGenericDelegate<string> strTarget =
            new MyGenericDelegate<string>(StringTarget);
        strTarget("Some string data");

        MyGenericDelegate<int> intTarget = IntTarget;
        intTarget(9);

        Console.ReadLine();
    }

    static void MyTarget(object arg) {
        if (arg is int) {
            int i = (int)arg;
            Console.WriteLine("++arg is: {0}", ++i);
        }

        if (arg is string) {
            string s = (string)arg;
            Console.WriteLine("arg in uppercase is: {0}", s.ToUpper());
        }
    }

    static void StringTarget(string arg) {
        Console.WriteLine("arg in uppercase is: {0}", arg.ToUpper());
    }

    static void IntTarget(int arg) {
        Console.WriteLine("++arg is: {0}", ++arg);
    }
}

    


Convert event to use generic delegate


   

/*
Example code from 


Chapter 18 - Generics
C# 2.0: The Complete Reference, Second Edition
by Herbert Schildt 
McGraw-Hill/Osborne ? 2006
*/       
       
using System;

class MyEventArgs : EventArgs {
  public int eventnum;
}

delegate void MyEventHandler<T, V>(T source, V args);

class MyEvent {
  static int count = 0;

  public event MyEventHandler<MyEvent, MyEventArgs> SomeEvent;

  public void OnSomeEvent() {
    MyEventArgs arg = new MyEventArgs();

    if(SomeEvent != null) {
      arg.eventnum = count++;
      SomeEvent(this, arg);
    }
  }
}

class X {
  public void handler<T, V>(T source, V arg) where V : MyEventArgs {
    Console.WriteLine("Event " + arg.eventnum + " received by an X object.");
    Console.WriteLine("Source is " + source);
    Console.WriteLine();
  }
}

class Y {
  public void handler<T,V>(T source, V arg) where V : MyEventArgs {
    Console.WriteLine("Event " + arg.eventnum + " received by a Y object.");
    Console.WriteLine("Source is " + source);
    Console.WriteLine();
  }
}

class Test {
  public static void Main() {
    X ob1 = new X();
    Y ob2 = new Y();
    MyEvent evt = new MyEvent();

    evt.SomeEvent += ob1.handler;
    evt.SomeEvent += ob2.handler;

    evt.OnSomeEvent();
    evt.OnSomeEvent();
  }
}

           
          


A simple generic delegate


   


using System;

// Declare a generic delegate.
delegate T GenericDelegate<T>(T v);

class GenDelegateDemo {
  static int sum(int v) {
    int result = 0;
    for(int i=v; i>0; i--)
      result += i;

    return result;
  }

  static string reflect(string str) {
    string result = "";

    foreach(char ch in str)
      result = ch + result;

    return result;
  }

  public static void Main() {
    GenericDelegate<int> intDel = sum;
    Console.WriteLine(intDel(3));

    GenericDelegate<string> strDel = reflect;
    Console.WriteLine(strDel("Hello"));
  }
}
           
          


constructor constraint

   
 

using System;


public class Starter {
    public static void Main() {
        MyClass obj = new MyClass();
        obj.MethodA<XClass>();
    }
}

public class MyClass {
    public void MethodA<T>()
                 where T : XClass, new() {
        Console.WriteLine("MyClass.MethodA");
        T obj = new T();
        obj.MethodB();
    }
}

public class XClass {
    public void MethodB() {
        Console.WriteLine("XClass.MethodB");
    }
}

    


Derivation Constraint

   
 
using System;

public class Starter {
    public static void Main() {

        // good
        MyClass<XClass, YClass> obj = new MyClass<XClass, YClass>();

        // good
        MyClass<XClass, WClass> obj2 = new MyClass<XClass, WClass>();

        // bad
        MyClass<WClass, YClass> obj3 = new MyClass<WClass, YClass>();

    }
}

public class MyClass<K, V>
    where K : XClass
    where V : YClass {
}

public class XClass {

}

public class YClass {
}

public class WClass : YClass {
}