声明委托类型:delegate <函数返回类型> <委托名> (<形参表>);
定义委托实例:<委托类型> <实例化名>=new <委托类型>(<注册函数>) 或 注册函数名;
匿名委托实例定义:<委托类型> <实例化名>=delegate(<形参表>){函数体};
注:匿名委托可使用lambda表达式
泛型委托类型定义:delegate <函数返回值类型,可使用泛型T1,T2等后面泛型参数中的一个> <委托名><T1,T2,T3...> (<形参表>)
泛型委托实例:<泛型委托类型><泛型参数>
例:delegate T1 Test<T1,T2>(T2 t2);//定义有两个泛型(T1,T2)的委托,T2作为委托函数返回类型,T1作为委托函数参数类型
链式委托:链式委托也称作 '多播委托'
链式委托的实现需从委托的实现来说起:委托实例中存在多个成员变量,其中有3个重要的成员变量,一个指向所需执行的代码区域,一个是目标实例的引用(即所引用的函数,如函数是静态函数,则此值为null),另一个便是链式委托实现的关键,即下一个委托的引用 next ,委托进行调用时,如next不为空则会继续进行调用,这个next便是链式委托的具体实现。
例:
static void fun1(){ Console.WriteLine(1); }
static void fun2(){ Console.WriteLine(2); }
static void fun3(){ Console.WriteLine(3); }
delegate void Test();
Test test = fun1;
test += fun2;
test += fun3;
则输出结果则为:1 2 3
根据委托的实现则能如下定义委托:
Test t1 = fun1;
Test t2 = fun2;
Test t3 = fun3;
Test test = t1 + t2 + t3;
test();
输出结果为:1 2 3
Test test = t1 + t2 + t3;此方式仅是将 t1,t2,t3 委托中的函数列表赋值到新的委托中,并非引用
则:
Test t1 = fun1;
Test t2 = fun2;
Test t3 = fun3;
Test test = t1 + t2 + t3;
t1 += fun2;
test();
输出结果依然是:1 2 3
同理:
Test t1 = fun1;
Test test = t1;
t1 += fun2;
test();
输出结果是:1
因为委托之间的相互赋值仅仅是将委托中的函数列表赋值,由此可见C#中的委托类型应该将赋值符号 '=' 进行了重载
注:委托的调用时如多播委托带参数,则所有函数的参数都一样。委托的另一种调用方式:test.Invoke()
委托调用的顺序:委托调用时,委托中的函数列表按照增加的先后顺序依次执行,若想自己对函数的执行顺序进行排序,则可以使用:GetInvocationList()函数,其返回值为 Delegate[],
如:
Test test = fun1;
test += fun2;
Delegate[] data= test.GetInvocationList();
test = (Test)data[1];
test += (Test)data[0];
则输出结果为:2 1
注:若链式委托函数有返回值,则返回的为最后一个执行的函数的值,若需要所有的返回值,则可以通过上述的test.GetInvocationList()方法一个个的执行委托链中的函数来得到所有的返回值。