• 委托定义:
    • 委托是一个引用类型,表示对具体特定参数列表和返回类型的方法的引用,在实例化委托时,可以其实例与任何具有兼容签名和返回类型的方法相关联;
    • 是安全封装方法的类型,类似于C和C++中的函数指针。这是来自微软官方的定义。再来看一下国内一些网站的定义:委托是一个类,它定义了方法的类型,
    • 使得可以将方法当作另一个方法的参数来进行传递,这种将方法动态地赋给参数的做法,可以避免在程序中大量使用if-else/switch 语句,同时使得程序
    • 具有更好的可扩展性。通过上面的定义一些基础不好的同学是不是,仍然不知道是用来干嘛,先别急咱们一点一点的来聊。    
    • 首先 通过定义咱们知道了一个很重要的信息:委托是一个类型、是类。既然委托是一个类,那么委托是不是也应该具有类的特性。
    • 咱们来看一下定义一个委托的方法:delegagte void Evenhandler();
    • 看到是不是有些小伙伴会问,“委托不是一个类吗?为什么在定义的时候这么一句就完了呢?”
    • 咱们来看一个实例,通过反编译工具咱们看一下,委托通过编译之后长什么样子

在图中咱们是不是可以清楚的看到,委托真的是一个类,继承自System.Object;并且它还有自己的方法:Invoke();BeginInvoke();EndInvoke();
那么怎么使用委托呢?看下面的例子:
public delegate void ShowResult(int a,int b);
static void Main(string[] args)
{
ShowResult showResult = Add;
//ShowResult showResult = New ShowResult(Add);
DelegateTest.Calculate(showResult , 5, 6);

        Console.Read();
    }

    public static void Add(int a, int b) {
        Console.WriteLine(a + b);
    }

    public static void Divide(int a, int b) {
        Console.WriteLine(a / b);
    }
    public static void Subtract(int a, int b) {
        Console.WriteLine(a - b);
    }
    public static void Multiply(int a, int b) {
        Console.WriteLine(a * b);
    }

看了上面的例子是不是感觉委托没有什么用,我么直接调用相应的方法不就行了吗?为什么还要绕个远路呢?
我们来看一下上面的实例,实例的目的是输出两个数的加、减、乘、除,这四个方法目前有一个共性的操作就是需要计算的结果进行输出。这仅仅是目前的需求,但是为了不挖坑,对传进去的参数是不是需要检测。
现在针对现在的程序添加一些规则:1:a、b都要是正整数;2:对每次操作都要写入日志。
考虑一下,添加这些规则,咱们是不是需要怎么修改代码。
public delegate int ShowResult(int a,int b);

    static void Main(string[] args)
    {
        ShowResult showResult = Add;
        //ShowResult showResult = New ShowResult(Add);
        DelegateTest.Calculate(showResult , 5, 6);
        Console.Read();
    }


    public static int Add(int a, int b) {
        return a + b;
    }
    public static int Divide(int a, int b) {
        return a / b;
    }
    public static int Subtract(int a, int b) {
        return a - b;
    }
    public static int Multiply(int a, int b) {
        return a * b;
    }

    public static void Calculate(ShowResult showResult, int a, int b) {
        if(a < 0 || b < 0){
            Console.WriteLine("参数有误");
        }else{
            System.Reflection.MethodInfo methodInfo = RuntimeReflectionExtensions.GetMethodInfo(showResult);
            Console.WriteLine("在这里写入一条日志" + methodInfo.ToString());
            Console.WriteLine(showResult(a, b));
            //Console.WriteLine(showResult?.Invoke(a, b)); ?.  null检查 C#6.0以上版本
        }
    }

向上面提取出所有相同的代码,放到一个方法中,把不相同的部分,定义成响应的方法。不论以后需要怎么改需求只需要更改Calcute 方法就行了,这样写代码的灵活性是不是更高,可扩展性是不是有了提升。
协变:

逆变:

下面介绍一下C#定义好的委托:
1、Action delegate 封装一个方法,该方法没有返回值。其中可以有0~16个参数。
pubilc delegate void Action(T obj); // T 泛型

2、Func<T, TResult> delegate 封装一个带有0~16个参数,且返回TResult类型的方法
public delegate TResult Func();

同时委托还有协变和逆变,下会再聊!

02-01 13:58