【学习笔记】C#中的委托(delegate)

  Delegate

一、什么是委托?

  委托是一种引用类型,它是函数指针的托管版本。在C#中,委托是一种可以把引用存储为函数的类型。委托可以引用实例和静态方法,而函数指针只能引用静态方法。委托的声明非常类似于函数,和函数不同的的是委托不带函数体,并且需要Delegate关键字。委托的声明指定了一个函数签名,其中包含参数列表和和一个返回类型。在定义了委托后,就可以声明该委托类型的变量,然后可以将这个变量初始化为与该委托有相同签名的函数进行引用,随后可以使用委托变量调用该函数。(ps:其实委托他丫的就是一个类,他的目的就是将方法可以作为其他方法的参数传递!)

  委托虽然与函数指针非常相似,但却不是指针。许多人把.NET中的委托理解为安全的函数指针,这是比较牵强的,委托实现的功能和函数指针非常类似的一点就是提供了程序回调机制。

二、委托四部曲:1、声明委托类型

            2、有一个方法包含了执行的代码

            3、创建委托实例

            4、调用委托实例

三、例子:(1)

using System;

namespace ConsoleApp
{
    class Program
    {
        //1、声明委托类型
        public delegate void AddDelete(int a, int b);
        //2、有一个方法包含了执行的代码
        public static void Add(int a, int b)
        {
            Console.WriteLine(a + b);
        }
        static void Main(string[] args)
        {
            //3、创建委托实例,使用了new 关键字,说明委托也是类,将方法名Add作为参数绑定到该委托实例             
            var adddelete = new AddDelete(Add);
            //4、调用委托实例             
            adddelete(1, 2);
            Console.ReadKey();
        }
    }
}

  (2)使用匿名方法,如下,可以看到这样就不需要再定义一个Add函数了,

using System;

namespace ConsoleApp
{
    class Program
    {
        public delegate void AddDelete(int a, int b);

        static void Main(string[] args)
        {
            AddDelete adddelete = delegate(int a, int b) { Console.WriteLine(a + b); };
            adddelete(1,2);
            Console.ReadLine();
        }
    }
}

四、C#中被委托的方法必须是静态的吗?

 

using System;

namespace ConsoleApp
{
    class Program
    {
        public delegate void AddDelete(int a, int b);
        private class MyClass
        {
            public void Add(int a, int b)
            {
                Console.WriteLine(a + b);
            }
        }
        
        static void Main(string[] args)
        {
            MyClass myClass=new MyClass();          
            var adddelete = new AddDelete(myClass.Add);             
            adddelete(1, 2);
            Console.ReadKey();
        }
    }
}

 

  通过上面的代码可以看出,委托既可以绑定静态方法也可以绑定实例方法。但是在绑定实例方法的时候,delegate的target属性就被设置为指向这个实例方法所属类型的一个实例对象。当绑定静态方法时,delegate的target属性就给NULL

 

 五、什么是多播委托?

  每个委托都只包含一个方法调用,调用委托的次数与调用方法的次数相同。如果要调用多个方法,就需要多次显示调用这个委托。当然委托也可以包含多个方法,这种委托成为多播委托

    调用过程中:1、多播委托包含一个以上方法的引用且必须是同类型的

          2、多播委托包含的方法必须返回void,否则会抛出run-time exception,并且不能带参数(但可以带引用参数)

    例子

using System;

namespace ConsoleApp
{
    public delegate int MyDel(int name);
    class Program
    {
        static int Add1(int a)
        {
            var b = 10 + a;
            Console.WriteLine(b);
            return b;
        }
        static int Add2(int a)
        {
            var b = 10 - a;
            Console.WriteLine(b);
            return b;
        }
        static void Main(string[] args)
        {
            var add = new MyDel(Add1);
            add += new MyDel(Add2);
            Console.WriteLine(add(10));
            Console.ReadKey();
        }
    }
}

也许,你看到这一段代码时,你会奇怪,+=不会给delegatesand重新赋值吗?

但是我想说你的担心是多余的,+=运算符,在我们之前的理解中,它具有赋值的作用,可这里为什么会与上边的代码 效果一样,与你的想象不一致,其实,这里的+=运算符被重载了 ,不再是我们一般理解的:

    int a=0,b=1;
   a+=b;//此时,a变成了 1
} 

在使用委托时,+=将会被重载,它的作用变成了 在不影响已赋值委托变量的前提下,为已赋值的委托变量再次添加一个引用委托方法
 也就是说,每使用一次 +=运算符,委托变量就会被加入一个委托方法,比如原来 委托变量被赋值了,使用一次+=运算符后,委托变量也就同时作为两个 委托方法的委托了 ,而且,它们运行的先后顺序与添加的先后顺序一致。

 

 

ps:此文章是本人参考网上内容加上自己的理解整合而成,如无意中侵犯了您的权益,请与本人联系。

 

  

posted @ 2017-10-24 20:34  千山慕雪  阅读(13700)  评论(3编辑  收藏  举报