C# 委托 delegate

委托是一种数据结构,它引用一个伙多个方法,对实例方法,还会引用这些方法对应的对象实例。

委托介绍

委托是一种引用方法的类型。一旦为委托分配了方法,委托将于该方法具有完全相同的行为。委托方法的使用可以像其他任何方法一样,具有参数和返回值。
public delegate int PerformCalculation(int x,int y);
委托具有以下特点:
- 委托类似与c++函数指针,但它是类型安全的
- 委托允许将方法作为参数进行传递
- 委托可以用于定义回调方法
- 委托可以链接在一起,可以对一个时间调用多个方法
- 方法不需要与委托签名精确匹配

委托声明

委托声明定义一个从System.Delegate类派生的类。委托实例封装一个调用列表,该列表队出一个或者多个方法,其中每个方法作为一个可调用的实体来引用。实例方法,由该方法和一个相关联的实例组成。静态方法,仅由一个方法组成。用一个适当的参数集来调用一个委托实例,就是用此给定的参数集来调用该委托实例的每个可调用实体。

//声明一个委托
delegate int D(int i ,double d);
class A{
     public static int M1(int a, double b){
         Console.WriteLine("A.M1");
         return (int)(a+b);
     }
 }

 class B {
     delegate int D2(int c, double d);
     public static int M1(int f, double g) {
         Console.WriteLine("B.M1");
         int x = 10; return x;
     }
     public static void M2(int k, double l) {
         Console.WriteLine("B.M2");
     }
     public static int M3(int g) {
         Console.WriteLine("B.M3");
         return g;
     }
     public static void M4(int g)
     {
         Console.WriteLine("B.M4");
     }
 }

 static void Main(string[] args)
 {
     D d1 = new D(A.M1);
     D d2 = new D(B.M1);
     D d3 = d1 + d2;
     d3(12, 2.23);
     Console.Read();
 }

委托创建

委托创建表达式用于创建委托类型的新实例。其参数必须是方法组委托类型的值
如果是方法组,则表示方法和(对于实例方法)为其创建委托的对象。如果是委托类型的值,则它标志为其创建副本的委托实例。

delegate double DoubleFunc(double x);
class D {
   //使用第二个Square初始化,因为该方法与委托的形参表和返回类型完全匹配,如果第二个方法不存在,则将发生编译时错误。
   DoubleFunc f = new DoubleFunc(Square);
   static float Square(float x) {
       return x * x;
   }
   static double Square(double x) {
       return x * x;
   }
}

委托实例化

委托实例是由“委托创建表达式”创建的。因此,新创建的委托实例采用以下各项之一

  • “委托创建表达式”中引用的静态方法
  • “委托创建表达式”中引用的目标对象(不能为null)和实例方法;
  • 另一个委托(delegate);
//A.M1 B.M1是一个方法
D d1 = new D(A.M1);
D d2 = new D(B.M1);
//d1,d2分别是委托
D d3 = d1 + d2;

委托实例一旦被实例化,将始终引用同一目标对象和方法。当组合两个委托或者从一个委托移除另一个时,将产生一个新的委托,该委托具有自己的调用列表;被组合或者被移除的委托的调用列表保持不变。

委托调用

当调用非空的,调用列表仅含有一个进入点的委托实例时,它调用调用列表中的方法,委托调用所使用的参数和返回的值均与该方法的对应项相同。
如果一个委托实例的调用列表有多个进入点,那么调用这样的委托实例就是按顺序同步调用调用列表中列的各个方法。以这种方法调用的每个方法都是用相同的参数集,即提供给委托实例的参数集。如果这样的委托调用包含引用参数,那么每个方法调用都将使用对同一变量的引用。
这是具体实例的定义

delegate void D(int x);
class C {
    public static void M1(int i) {
        Console.WriteLine("C.M1:" + i);
    }
    public static void M2(int i)
    {
        Console.WriteLine("C.M2:" + i);
    }
    public void M3(int i)
    {
        Console.WriteLine("C.M3:" + i);
    }
}

这是测试代码

static void Main(string[] args)
{
    D cd1 = new D(C.M1);
    cd1(-1);    //C.M1
    D cd2 = new D(C.M2);
    cd2(-2);    //C.M2
    D cd3 = cd1 + cd2;  //C.M1 C.M2
    cd3(10);
    cd3 += cd1;
    cd3(20);    //C.M1,C.M2,     C.M1
    C c = new C();
    D cd4 = new D(c.M3);
    cd3 += cd4;
    cd3(30);    //C.M1,C.M2,     C.M1    C.M3
    cd3 -= cd1; //删除M1
    cd3(40);
    cd3 -= cd4;
    cd3(50);
    cd3 -= cd2;
    cd3(60);
    //无效
    cd3 -= cd2;
    cd3(60);
    cd3 -= cd1;
    //无效
    //cd3(40);     //报错
    cd3 -= cd1;
    Console.Read();
}

运行结果如图:
这是运行结果

结束!

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值