C#委托的详细讲解

C#委托的详细总结

1.什么是委托

       委托是C#中一种类型,它的作用相当于C语言中的函数指针,它定义了方法的类型,使得可以将方法当作另一个方法的参数来进行传递,这种将方法动态地赋给参数的做法,可以避免在程序中大量使用if-else(Switch)语句,同时使得程序具有更好的可扩展性。
       委托和类是同级别的,我们可以直接将delegate看成为关键字class,区别为class里存放的是一系列方法,属性,字段,事件,索引。而delegate里存放的是一系列具有相同类型参数和返回回类型的方法的地址的地址。可以看着为储存方法的载体。

2.声明委托

delegate <函数返回类型> 委托名(函数参数)
例:public delegate void MyDelegate(string name);

3.实例化委托

(1) 常规实例化委托
语法:<委托名> 实例化名 = new <委托名>(注册函数)
注意:注册函数不包含参数,或者可以直接将一个注册函数赋值给委托。 例:

MyDelegate  _md = new MyDelegate(method);

(2)匿名方法实例化委托
语法: <委托类型> <实例化名>=delegate(<函数参数>){函数体}; 例:

 MyDelegate  md = delegate(string s) 
 {
   	Console.WriteLine(s); 
 };

(3)使用Lambda表达式实例化委托
语法:参数列 =>语句或语句块
用法规则:

  1. “Lambda表达式”的参数数量必须和“委托”的参数数量相同;
  2. 如果“委托”的参数中包括有ref或out修饰符,则“Lambda表达式”的参数列中也必须包括有修饰符;     例:
 class Test
    {
        public delegate void MyDelegate(out int x);//声明委托
        static void Print(MyDelegate test)
        {
            int i;
            test(out i);
            Console.Write(i);
        }
        static void Main()
        {
            Print((out int x) => x = 3);
            Console.Read();
        }
    }

       这三种方法都可以实现功能,lamda表达式只是简化了委托的声明,以及委托的实例化和调用。 从下面的例子中让我们看看三者的区别:

class Program
    {
        //声明委托
        delegate int MyDelegate(int x, int y);
        static void Main(string[] args)
        {
            //实例化委托
            //1、使用new关键字
            MyDelegate _md = new MyDelegate(Sum);
            //2、使用匿名方法
            MyDelegate md= delegate(int x, int y)
            {
                return x + y;
            };
            //3、使用Lambda表达式
            MyDelegate mdLambda = (int x, int y) => { return x + y; };
        }
        static int Sum(int x, int y)
        {
            return x + y;
        }
    }

4.多播委托

       多播委托继承自 Delegate,即 “多路广播委托”(MulticastDelegate)。从名字就可以看出,此种委托可以像广播一样将影响信息“传播”到四面八方。多播委托类拥有一个方法调用列表,调用委托时,它就会逐一调用该列表中的方法,从而实现多重影响。
       在现实生活中,多播委托的例子是随处可见的,例如某点餐的应用程序,既可以预定普通的餐饮也可以预定蛋糕、鲜花、水果等商品。在这里委托相当于点餐平台,每一个类型的商品可以理解为在委托上注册的一个方法。

4.1 多播委托的实例化

       多播委托的初始化可以像普通委托一样,传入一个签名相同的实例方法。同时,多播委托重载了 += 运算符和 -= 运算符,用来向其调用列表中添加或者删除方法。调用多播委托时,方法将按照添加的顺序被依次调用。
我们定义一个简单的执行加减运算的委托,并利用+=运算符和Lambda表达式为该多播委托添加两个方法:

public delegate int AddDelegate(int a);
AddDelegate md = new AddDelegate(i => i + 10);
md += i => i - 10;

4.2 多播委托的调用与返回结果

!!!使用委托,直接md( )就相当于使用了md. Invoke()
调用上面的AddDelegate,传入一个参数10:

Console.WriteLine(md(10));

运行代码,得到结果:

0

        你们有疑问吗?为什么有两个方法,怎么只有一个返回值呢?
        实际上,两个方法都被调用了。案例讲解:
        多播委托按照顺序调用其列表中的方法。首先,参数先调用了 i => i + 10 函数,得到了函数返回值20。然而,委托的调用并没有停止, 而是继续调用剩余的方法。然后继续对参数调用 i => i - 10 函数,得到新的返回值0,上个函数的返回值被覆盖。至此委托调用结束,返回最后调用方法的返回结果。
        因此,一个有非空返回值的多播委托通常是没有意义的,因为只能获得最后一个方法的返回结果。所以通常,多播委托的返回类型为 void。

4.3 多播委托的逐个调用

        那么对于返回类型不为空的多播委托来说,有没有办法得到所有方法的返回结果呢?答案是有,多播委托提供了一个 GetInvocationList () 方法,通过它可按顺序获取并执行调用列表中的方法。用法举例:

Console.WriteLine("每个都调用:");
foreach (AddDelegate f in md.GetInvocationList())
    Console.WriteLine(f.Invoke(10));

如此便可逐个得到方法的输出结果:

每个都调用:
20
0

5. 泛型委托

5.1 泛型委托原型

        委托也支持泛型的使用 ,泛型委托原型:delegate <委托名><T1,T2,T3…> (T1 t1,T2 t2,T3 t3…)

5.2 内置泛型委托

Func委托
       Func委托代表着拥有返回值的泛型委托。Func有一系列的重载,形式如 Func<T1,T2, … TResult>,其中TResult代表委托的返回值类型,其余均是参数类型。只有一个T时,即Func,代表该委托是无参数的。.NET封装了最多16个输入参数的Funct<>委托。
       !!!若方法返回 void ,由于 void 不是数据类型,因此不能定义Func委托。
Action委托
       Action委托代表返回值为空 void 的委托,它也有一些列重载,最多拥有16个输入参数。用法与Func相同。
Predicate委托
       这个一般用的较少,它封装返回值为bool类型的委托,可被Func代替。

6.委托的用处

       说白了,委托就是第三方,调用者告诉第三方要做什么,然后调用者就不用管了 这个委托(第三方)就会去调用方法去帮你实现。
使用委托的好处:
       1.相当于用方法作为另一方法参数(类似于C的函数指针)
       2.在两个不能直接调用的方法中作为桥梁,如:在多线程中的跨线程的方法调用就得用委托。
       3.当不知道方法具体实现什么时使用委托,如:事件中使用委托。

  • 6
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值