C#委托

来源:互联网 发布:海岛导弹升级数据 编辑:程序博客网 时间:2024/05/01 18:21

可能很多初学者都听说过委托,但对于委托到底是什么就不得而知了。C#中用关键字delegate(英[ˈdeliɡit,ˈdelɪɡət])生命委托,为此我专门查了一下这个单词的音标和意思解释为:代表;托付。

那么究竟什么是委托呢?我们还是没有说明,我翻了一些书籍,对委托的解释:它是一种数据类型,和引用类型类似,不过和一般的类相比,委托的实例不是在堆中的数据,而是一个方法。委托类似于引用类型,和C++中的函数指针很相似,但是不同之处就在于,他不是存在于堆中的。正是有了委托我们才得以将函数打包成一个变量进行传递。这就是说,我们不止能够将数据作为参数传递,还可以将一个函数作为参数进行传递,这样就可以在需要的时候方便的进行控制的反转(Ioc,控制反转)。

说了那么多没有实际的例子还是理解不了,下面我们通过几个实例来看一下什么是委托:

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

namespace Delegate
{
    class Program
    {

        public delegate double DelegateOne(double d);//声明一个委托
        public static double FunctionOne(double d)
        {
            return d * 2;
        }
        static void Main(string[] args)
        {
            DelegateOne dlgt = new DelegateOne(FunctionOne);//也可以直接DelegateOne dlgt = FunctionOne;
            double d=dlgt(3);
            Console.WriteLine(d);
            Console.ReadKey();
        }
    }
}

这个例子比较简单,我们首先声明了一个委托DelegateOne,它有一个参数是double类型,返回值也是double类型的。然后定义了一个结构和它类似的方法FunctionOne,参数是double类型返回值也是double类型。在main方法中我们new了一个委托的实例,将FunctionOne传递给它,这就是说实例dlgt就有了FunctionOne的功能(但这里必须保证委托和方法的结构相同)。

下面我们看一下多路广播委托简称多播委托,也就是委托和方法的返回值是void类型。这是我们可以看到这种委托我们可以使用+=和-=来链入和去除多个委托。

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

namespace Delegate
{
    class MulticastDelegate
    {
        public delegate void DelegateOne(double d);//声明一个委托
        public static void FunctionOne(double d)
        {
            Console.WriteLine(d * 2);
        }
        public static void FunctionTwo(double d)
        {
            Console.WriteLine(d * d);
        }
        static void Main(string[] args)
        {
            DelegateOne dlgt = new DelegateOne(FunctionOne);
            dlgt += new DelegateOne(FunctionTwo);//这就是多播委托的好处
            dlgt(3);
            Console.ReadKey();
        }
    }
}

上面这个例子的运行结果是6   9,不是一个结果,而是相当于同时执行了两个方法,这也就是多播委托的特点。我们不仅可以+=一次还可以多次,而且还可以-=多次。我们对上述代码中的Main方法进行稍微的修改:

static void Main(string[] args)
        {
            DelegateOne dlgt = new DelegateOne(FunctionOne);
            dlgt += new DelegateOne(FunctionTwo);//这就是多播委托的好处
            dlgt(3);
            Console.ReadKey();
            dlgt -= new DelegateOne(FunctionTwo);
            dlgt(3);
            Console.Read();
        }

这是的运行结果先是6    9,而后当你按了一个按键之后显示了6.说明什么问题呢,6   9的输出我们上面已经解释过了,因为我们链入了两个方法。后面一个是因为我们去点了一个方法FunctionTwo而只剩下FunctionOne,所以输出6.

多播委托,在教材上是说返回值必须是void,事实上通过实验我们会发现其实如果返回值不是void也可以,只不过这是我我们的就收结果是最后一个链入委托方法的返回值。

我们在前面提到了委托不是存放在堆中的,而是作为一个方法,下面我们具体看看是不是这样:

我们知道,如果是存到了堆中,例如类A和类B(类肯定是在堆中存放的),如果我们另A a=new A(); B b;b=a;这是我们修改b,就可以影响到a。换句话说如果委托也是这样,我们也可以看到这样的结果,那么是不是呢?

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

namespace Delegate
{
    class DelegateNotRef
    {
        public delegate string DelegateOne();
        static void Main(string[] args)
        {
            int x = 3;
            DelegateOne dlgt = new DelegateOne(x.ToString);
            Console.WriteLine(dlgt());

            x = 4;
            Console.WriteLine(dlgt());
            Console.WriteLine(x.ToString());
            Console.Read();
        }
    }
}

可以看到,我们输出为3 3 4,而不是3 4 4,说明我们在修改x=4后,委托中的东西并没有随之修改,也就说明了委托不是在堆中存储的。

接下来我们进一步看看泛型委托:

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

namespace Delegate
{
    class GnericDelegate
    {
        public delegate string DelegateOne(T t,S s);

        public static string FunctionOne(string s, int i)
        {
            return s + i.ToString();
        }

        public static string FunctionTwo(string s1, string s2)
        {
            return s1 + s2;
        }

        static void Main(string[] args)
        {
            DelegateOne dlgt = new DelegateOne(FunctionOne);
            Console.WriteLine(dlgt("ab", 42));

            DelegateOne dlgt2 = new DelegateOne(FunctionTwo);
            Console.WriteLine(dlgt2("abc","def"));

            Console.Read();
        }
    }
}

很简单,和我们的其他类型的泛型没有多大的差别,这里就不再赘余!

原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 淄博市人力资源和社会保障网 甘肃人力资源社会保障厅 重庆人力和社会保障网 淄博市人力资源社会保障网 山东省人力资源保障厅 贵阳人力资源网 重庆人力社会保障网 重庆人力资源 广州市人力资源社会保障局 甘肃人力资源保障厅 广州市人力资源和社会保障局 人力社会保障局社保网 深圳市人力资源社会保障局 贵阳人力资源 深圳市人力资源和社会保障局 重庆市人力资源和社会保障局 青岛市人力资源和社会保障局 罗德岛人力资源部 河南省人力资源和社会保障厅 重庆人力资源和社保局网 潍坊市人力资源和社会保障局 台山人才人力资源网 河南省人力资源社会保障厅 重庆市人力资源社会保障局 潍坊市人力资源社会保障局 广州市人力资源保障局 深圳市人力资源保障局 北京市人力资源和社会保障局 重庆市人力资源社会保障网 成都市人力资源和社会保障局 北京市人力资源社会保障局 吴江人力资源 贵阳人力资源社会保障网 重庆市人力资源和社会保障网 漯河市人力资源和社会保障局 成都市人力资源社会保障局 罗德岛人力资源 漯河市人力资源社会保障局 青岛市人力资源社会保障局 淄博人力资源网 济南市人力资源和社会保障局