委托

1.什么是委托?

答:自我的理解委托就是对方法的分类而委托的实例就是一个具体的方法,简单的理解:就像是Person这个类一样Person类的一个实例就是一个人。而委托只不过是把“一个人”变成了“一个方法”这么简单。当然这些方法必须有共同的特性,就行人一样每一个人都有姓名身份证号等。而委托也一样那就是这些方法必须有相同的签名。通俗一点说就是这些方法必须有相同的返回值类型以及相同的参数列表。还有就是所有的方法必须与委托所定义的原型相同。

例如:


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

namespace ConsoleApplication2
{
    public delegate void Delan(string name);//定义一个无返回值,参数是string类型的委托
    class Program
    {
        static void Main(string[] args)
        {
            Delan del = new Delan(work);  //实例化一个委托,并未其赋值,这里值得注意的是实例化委托的时候必须有传一个方法类型的参数
            del("张三");
            Delan del1 = new Delan(run);
            del1("李四");

            Console.ReadKey();
        }
        public static void work(string name)//定义一个无返回值,且参数为string类型的参数。
        {
            Console.WriteLine("{0}在工作呢!",name);
        }
        public static void run(string s)///定义一个无返回值,且参数为string类型的参数。
        {
            Console.WriteLine("{0}在跑步呢!",s);
        }

        /*
         *由上述例子可以看出,定义的委托是无返回值,有一个参数且参数的类型是string
         *而我们所定义的方法类型也是无返回值,有一个参数且参数类型是string,这就是方法必须与委托所定义的原型相同
         *如果与委托的原型是不同的那你在实例化一个委托并为其赋值时将会出错。
         */
    }
    
}

运行的结果


这里值得一说的是这里的方法可以是不同的类中的,也可以是非静态的我们上面所举的例子是静态方法。  看到这里相信很多人就要说为什么这么麻烦啊还要通过委托来调用方法,其实委托最大的强大之处在于,委托可以异步回掉,委托可以一次调用多个方法也就是多播委托。我们先看一下何为异步回掉。

例如:

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

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            MyDel del = new MyDel(DelegateMethod);//实例化一个委托,并把DelegateMethod方法赋值给del让del指向一个具体的方法。
            Callback(5, 6, del);//在此处del指的就是DelegateMethod方法,是一个具体的方法。而DelegateMethod方法的作用只是输出一句话。
            Console.ReadKey();

        }
        public static void DelegateMethod(string str)
        {
            Console.WriteLine(str);
        }
        public static void Callback(int a, int b, MyDel call)//定义一个方法,把方法以委托类型的形式作为方法的参数传入方法内。
        {
            call("a+b的值为:"+ (a + b).ToString());//调用委托类型的方法。
 
        }
    }
    public delegate void MyDel(string s);//定义一个无返回值,有一个参数的委托。
}

再次解释一下何为异步回掉,

这里我们定义的一个方法就是Callback,这个方法比较特殊,这里的Callback方法有三个参数,两个int类型的一个是我们所定义的委托类型的也就是MyDel类型的,

在这里我们调用这个方法时需要传入三个参数,那就是两个int类型的,这个好理解最重要的就是下面,

这个MyDel是什么类型的,我们在上面说过委托是一类方法的集合,

因此我们在此先把委托看做是一个类(其实委托就是一个类)这样我们就可以很好的理解public delegate void MyDel(string s)这行代码了

我们可以把MyDel这是名称是类的名称。只不过这个类里面的是一些无返回值的,但是有一个string参数的一些方法。

这样解释的话相信我们就很好理解这个MyDel类型的参数了吧。

我们在再看这个方法在调用的时候是怎么调用的。

Callback(5, 6, del);

我们在调用这个方法的时候传入的第三个参数是一个委托的实例变量,但是这个实例变量搭载的是有方法的现在这个委托的实例del所指带的是一个具体的方法,因为我们在上一步的实例化委托的时候我们为其赋值了

MyDel del = new MyDel(DelegateMethod);

所以我们就可以理解为del==DelegateMethod;还有就是我们值得注意的就是这个DelegateMethod方法是一个无返回值的且是有一个string类型的参数的,所以我们在调用的时候也只能传入一个参数否则的话会出错。

还有就是委托类型的参数传入到方法体中的时候也可以像操作其他参数一样对其进行操作。这就是委托的强大之处之一。

现在我们看看什么叫多播委托

例如:

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

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {

            MyDel del = new MyDel(Working);
            del += OffDuty;
            del += GoHome;
            del("张三");
            Console.ReadKey();
        }
        public static void Working(string name)
        {
            Console.WriteLine("{0}在工作呢!",name);
        }
        public static void OffDuty(string s)
        {
            Console.WriteLine("{0}下班了",s);
        }
        public static void GoHome(string name1)
        {
            Console.WriteLine("{0}走在回家的路上!",name1);
        }
     
    }
    public delegate void MyDel(string s);//定义一个无返回值,有一个参数的委托。
}

运行结果:

相信看到上面的代码以及运行结果相信我们看到了多播委托的强大之处。

我们再次分析一下上面的代码。

我们先看一下我们所定义的几个方法:

 public static void Working(string name)


 public static void OffDuty(string s)


 public static void GoHome(string name1)

首先观察一下我们所定义的方法有什么共同之处

1.它们都是静态的。

2.它们都是无返回值的也就是返回值类型都是void。

3.它们都有一个参数,并且返回值类型为string。

现在我们再看一下我们所定义的委托:

public delegate void MyDel(string s)

1.我们定义的委托是无返回值的也是void

2.我们所定义的委托也是只有一个返回值,且返回值类型为string。

由此我们可以看出我们定义委托的时候已经决定了方法的原型。那就是我们如果要再委托对象上搭载方法的时候必须绝对符合我们所定义的委托的原型不然就会出现错误。这也再次验证了我们前面所说委托就是一类的方法的集合。

 MyDel del = new MyDel(Working);
            del += OffDuty;
            del += GoHome;
del(“张三”);

这几句的意思是实例化一个委托对象然后让这个委托对象依次搭载Woking ,OffDuty, GoHome方法,而我们在搭载这些方法的同时就相当于依次的在多播委托链上依次的注册这些方法(就像是一条流水线一样)其实在多播委托的类中(继承与委托类)相比于委托类就多了一个委托链。er我们在调用的时候就会调用整条链上的委托对象而每一个委托对象所指向的就是一个具体的方法。所以就可以依次调用委托链上的所有方法。

委托可以搭载不同的类的方法例如:

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

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            OneDay day = new OneDay();
            MyDel del = new MyDel(day.eat);
            MyDel del2 = Working;
            MyDel del3 = OffDuty;
            MyDel del4 = GoHome;
            MyDel del5 = day.eat;
            MyDel del6 = day.Run;
            MyDel del7 = day.Sleep;
            MyDel alldel = del + del2;
            alldel += del3;
            alldel += del4;
            alldel += del5;
            alldel += del6;
            alldel += del7;
            alldel("张三");
            Console.ReadKey();
        }
        public static void Working(string name)
        {
            Console.WriteLine("{0}在工作呢!",name);
        }
        public static void OffDuty(string s)
        {
            Console.WriteLine("{0}下班了",s);
        }
        public static void GoHome(string name1)
        {
            Console.WriteLine("{0}走在回家的路上!",name1);
        }
     
    }
    public delegate void MyDel(string s);//定义一个无返回值,有一个参数的委托。
    public class OneDay
    {
        public void eat(string name2)
        {
            Console.WriteLine("{0}在吃饭",name2);
        }
        public void Sleep(string name3)
        {
            Console.WriteLine("{0}在睡觉!",name3);
        }
        public void Run(string name4)
        {
            Console.WriteLine("{0}在跑步!",name4);
        }
    }
}

运行结果:

由上述的例子我们可以看出很多委托的特性

例如:

1.委托是一类方法的集合。

2.委托所搭载的方法可以静态的也可以是非静态的,可以同属于一个类也可以不属于同一个类,只要绝对的符合委托类型的原型即可。

3.一个委托对象可以搭载多个委托对象,以及多个方法。

4.委托在调用方法的时候会根据你所搭载(注册)的方法的顺序依次调用你所搭载的所有方法。

其中委托类型还有几种方法例如:

委托的类中的静态方法帮助我们操作委托链:


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


namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            OneDay day = new OneDay();
            MyDel del = new MyDel(day.eat);
            MyDel del2 = Working;
            MyDel del3 = OffDuty;
            MyDel del4 = GoHome;
            MyDel del5 = day.eat;
            MyDel del6 = day.Run;
            MyDel del7 = day.Sleep;
            MyDel alldel = del + del2;
            alldel += del3;
            alldel += del4;
            alldel += del5;
            alldel += del6;
            alldel += del7;
            alldel -= del2;
            alldel("张三");
            Console.ReadKey();
        }
        public static void Working(string name)
        {
            Console.WriteLine("{0}在工作呢!",name);
        }
        public static void OffDuty(string s)
        {
            Console.WriteLine("{0}下班了",s);
        }
        public static void GoHome(string name1)
        {
            Console.WriteLine("{0}走在回家的路上!",name1);
        }
    
    }
    public delegate void MyDel(string s);//定义一个无返回值,有一个参数的委托。
    public class OneDay
    {
        public void eat(string name2)
        {
            Console.WriteLine("{0}在吃饭",name2);
        }
        public void Sleep(string name3)
        {
            Console.WriteLine("{0}在睡觉!",name3);
        }
        public void Run(string name4)
        {
            Console.WriteLine("{0}在跑步!",name4);
        }
    }
}


运行结果:

 我们用MyDel类的移除方法移除了del2方法:

alldel -= del2;

这句话就让我们把del方法移除了委托链所以在执行的时候就没有调用del方法。

我们再调用方法把del方法加上看看,是否能加上。

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

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            OneDay day = new OneDay();
            MyDel del = new MyDel(day.eat);
            MyDel del2 = Working;
            MyDel del3 = OffDuty;
            MyDel del4 = GoHome;
            MyDel del5 = day.eat;
            MyDel del6 = day.Run;
            MyDel del7 = day.Sleep;
            MyDel alldel = del + del2;
            alldel += del3;
            alldel += del4;
            alldel += del5;
            alldel += del6;
            alldel += del7;
            alldel -= del2;
            alldel += del2;
            alldel("张三");
            Console.ReadKey();
        }
        public static void Working(string name)
        {
            Console.WriteLine("{0}在工作呢!",name);
        }
        public static void OffDuty(string s)
        {
            Console.WriteLine("{0}下班了",s);
        }
        public static void GoHome(string name1)
        {
            Console.WriteLine("{0}走在回家的路上!",name1);
        }
     
    }
    public delegate void MyDel(string s);//定义一个无返回值,有一个参数的委托。
    public class OneDay
    {
        public void eat(string name2)
        {
            Console.WriteLine("{0}在吃饭",name2);
        }
        public void Sleep(string name3)
        {
            Console.WriteLine("{0}在睡觉!",name3);
        }
        public void Run(string name4)
        {
            Console.WriteLine("{0}在跑步!",name4);
        }
    }
}

运行结果:

由运行结果可以看出我们是吧del2方法加上去了但是调用的顺序却发生改变了

所以我们可以通过:

 alldel += del2;

委托链进行方法的的加运算。由此我们也可以得出我们可以通过+=和-=对委托链进行方法的加减运算。

而我们通过加等于和减等于就能对其进行运算的原因就是多播委托类为委托链所提供的两个静态方法所实现。

如下两个方法:

public static Delegate Remove(Delegate source, Delegate value);
public static Delegate Combine(params Delegate[] delegates);

至此我所理解的委托“理”完,希望对自己能有一个提高,也希望大神们指正。

原文地址:https://www.cnblogs.com/lizanqirxx/p/5364673.html