委托 delegate关键字,可以实现将函数作为参数传递
1、基本用法

委托是一个数据类型,与类同等级,用于指向某一个方法,然后通过委托来调用该方法

static delegate int delegateAdd(int a,int b);//创建一个返回值int,两个参数都是int的委托
class wt{
    //先创建两个示例函数,返回值和参数类型与委托相同,才能传递给委托.为方便演示,暂时方法设置成static
    public static int add1(int a,int b){
          return a+b;  
    }
    public static int add2(int a,int b){
          return a+b+10;  
    }
    static void Main(string[] args){
        delegateAdd a = new delegateAdd(add1);//实例化一个委托,将add方法赋给委托,也可以delegateAdd a =add1;简写
        delegateAdd(1,2);//等同于调用add1,返回3
        delegateAdd+=add2;//可以用+=和-=操作委托当中包含的方法,委托可以看做一个方法的集合
        delegateAdd(1,2);//调用add1和add2,委托的返回值为最后一个方法的返回值,此处为13
    }
}    

2、Action和Func

系统本身有两个定义好的委托类型,其中Action是无返回值(void)类型方法,Func有返回值

class wt{
    public static void say(string s){//参数string,无返回值
        Console.WriteLine(s);
    }  
    public static string add(int a,int b){//参数两个int,返回值string
        int c=a+b;
        Console,WriteLine(c);
        return c.toString();
    }
    static static void main(string[] args){
        Action<string> say1 = say;//Action示例,尖括号内是参数类型列表,实例化一个无返回值委托实例
        say1("Hello World");//输出Hello World
        Func<int,int,string> add1 = add;//Func示例,尖括号里前面是参数列表,最后一个是返回值类型,实例化一个有返回值委托实例
        add1(1,2);//输出3,返回字符串类型"3"
    }
}

3、通过利用实例,将方法名作为参数的实现

class wt{
    public void say(string s){
        Console.WriteLine("我想说:"+s);  
    }
    public void eat(string s){
        Console.WriteLine("我吃了:"+s);  
    }
    public void dosth(Action<string> act,string c){
        act(c);  
    }
    static void Main(string[] args){
        wt wt1 = new wt();
        wt.dosth(wt.say,"你好");
        wt.dosth(wt.eat,"苹果");
    }
}

4、使用匿名函数作为方法的参数

基本格式 方法名 delegate (参数列表){方法体} );

class wt{
    public void dosth(Action<string> act,string c){
        act(c);  
    }
    public string dosth_2(Func<int,int,string> act,int a,int b){
        act(c);  
    }
    static void Main(string[] args){
        wt wt1 = new wt();
        //以下为使用delegate构造匿名函数方法
        wt.dosth(delegate (string s){Console.WriteLine("我想说:"+s);},"你好");
        wt.dosth(delegate (string s){Console.WriteLine("我吃了:"+s);},"苹果");

        wt.dosth_2(delegate (int a,int b){
            int c = a+b;
            return c.toString();
        },1,2);
    }
}

5、匿名函数的更简单写法,lambda表达式

基本格式  方法名( (参数列表) => {方法体} );

class wt{
    public void dosth(Action<string> act,string c){
        act(c);  
    }
    public string dosth_2(Func<int,int,string> act,int a,int b){
        act(c);  
    }
    static void Main(string[] args){
        wt wt1 = new wt();
        //以下为使用lambda表达式构造匿名函数方法
        wt.dosth((string s)=>{Console.WriteLine("我想说:"+s);},"你好");
        wt.dosth((string s)=>{Console.WriteLine("我吃了:"+s);},"苹果");

        wt.dosth_2((int a,int b)=>{
            int c = a+b;
            return c.toString();
        },1,2);
    }
}

6、使用委托构造事件

可以类比一些图形界面编程中的监听,当执行某操作时触发,并执行某一操作

下面以Dog对象为例,有run方法,有v速度属性,事件设置为当狗在跑的时候触发,进行广播速度值

public class Dog{
    public int v;
    public event Action onRun;//event关键字定义事件,无参数直接用Action不加尖括号
    public Dog(){//初始化v
        v=10;
    }
    public void run(){
        Console.WriteLine("狗在跑");
        onRun();
    }
}    
class wt{
    static void Main(string[] args){
        Dog dg=new Dog();
        dg.onRun += (()=>{Console.WriteLine("速度是:"+dg.v);});
        dg.run();
        //输出结果:
        //狗在跑
        //速度是:10
    }
}    
//如果需要对事件进行删除,那么可以不使用匿名函数