C# 委托知识总结


1.怎么着是信托,为啥要利用委托

 

小编正在埋头苦写程序,猛然想喝水,可是又不想本身去掉杯水而围堵本人的思路,于是自身就想让女对象去给自家倒水。她去给本身倒水,首先本身得让她了解自身想让她怎么,通告他后来作者得以继续写本身的程序,而倒水的办事就付出了他。那样的进度就也正是多个信托。

寄托概述

将艺术调用者和对象措施动态关联起来,信托是七个类,所以它和类是同级的,能够透过委托来掉用艺术,不要误以为委托和措施同级的,方法只是类的分子。委托定义了措施的档期的顺序(定义委托和与之对应的不二秘技必得拥有相似的参数个数,並且类型相似,重返值类型相仿卡塔尔,使得能够将艺术当做另三个主意的参数来拓宽传递,这种将艺术动态地赋给参数的做法,可以免止在程序中大批量施用If-Else(Switch)语句,同一时候使得程序有所更加好的可扩充性。

 

在程序过程中,当程序正在管理某些事件的时候,俺索要其余的程序代码去援助管理部分政工,于是委托另一个主次模块去管理,而委托就可以达到这种目标,小编得以行使委托通告其余的次第模块,该去调用哪个函数方法。委托其实就起到了那般叁个效果与利益,将函数签字传递到了另贰个函数中。只怕那样讲依旧稍稍模糊,看看后边的现实性实例。

底子委托(Delegate)

在.Net中宣示委托行使首要词delegate,委托具有各个选取办法(以下均为协同委托调用卡塔 尔(阿拉伯语:قطر‎:

 1     /// <summary>
 2     /// 普通委托基础调用方式(同步委托)
 3     /// </summary>
 4     public class Delegates
 5     {
 6         /// <summary>
 7         /// 定义有参无返回值委托
 8         /// </summary>
 9         /// <param name="i"></param>
10         public delegate void NoReturnWithParameters(string o);
11         /// <summary>
12         /// 构造函数实例化
13         /// </summary>
14         public void DemoOne()
15         {
16             NoReturnWithParameters methord = new NoReturnWithParameters(this.Test);
17             methord.Invoke("One-ok");
18         }
19         /// <summary>
20         /// 赋值对象
21         /// </summary>
22         public void DemoTwo()
23         {
24             NoReturnWithParameters methord = this.Test;
25             methord.Invoke("Two-ok");
26         }
27         /// <summary>
28         /// DotNet 2.0 
29         /// </summary>
30         public void DemoThree()
31         {
32             NoReturnWithParameters methord = new NoReturnWithParameters(
33                 delegate (string o)
34                      {
35                          Console.WriteLine("有参无返回值:{0}", o);
36                      }
37             );
38             methord.Invoke("Three-ok");
39         }
40         /// <summary>
41         /// DotNet 3.0 
42         /// </summary>
43         public void DemoFour()
44         {
45             NoReturnWithParameters methord = new NoReturnWithParameters(
46                 (string o) =>
47                     {
48                         Console.WriteLine("有参无返回值:{0}", o);
49                     }
50             );
51             methord.Invoke("Four-ok");
52         }
53         /// <summary>
54         /// 委托约束
55         /// </summary>
56         public void DemoFive()
57         {
58             NoReturnWithParameters methord = new NoReturnWithParameters(
59                 (o) =>
60                 {
61                     Console.WriteLine("有参无返回值:{0}", o);
62                 }
63             );
64             methord.Invoke("Five-ok");
65         }
66         /// <summary>
67         /// 方法只有一行去则掉大括号及分号
68         /// </summary>
69         public void DemoSix()
70         {
71             NoReturnWithParameters methord = new NoReturnWithParameters((o) => Console.WriteLine("有参无返回值:{0}", o));
72             methord.Invoke("Six-ok");
73         }
74         public void DemoSeven()
75         {
76             NoReturnWithParameters methord = (o) => Console.WriteLine("有参无返回值:{0}", o);
77             methord.Invoke("Seven-ok");
78         }
79         /// <summary>
80         /// 定义有参无返回值测试方法
81         /// </summary>
82         /// <param name="o"></param>
83         private void Test(string o)
84         {
85             Console.WriteLine("有参无返回值:{0}", o);
86         }
87         /*
88          * 作者:Jonins
89          * 出处:http://www.cnblogs.com/jonins/
90          */
91     }

 

 

一同委托&异步委托

四头委托:委托的Invoke情势用来拓宽协同调用。同步调用也能够叫堵塞调用,它将闭塞当前线程,然后实行调用,调用达成后再持续向下开展。

异步委托:异步调用不打断线程,而是把调用塞到线程池中,程序主线程或UI线程能够继续实践。委托的异步调用通过BeginInvokeEndInvoke来实现。

以下为异步委托调用方式:

 1     class Program
 2     {
 3         /// <summary>
 4         /// 定义有参无返回值委托
 5         /// </summary>
 6         /// <param name="i"></param>
 7         public delegate void NoReturnWithParameters(string o);
 8         static void Main(string[] args)
 9         {
10             NoReturnWithParameters methord = new NoReturnWithParameters(Test);
11             Console.WriteLine("主线程执行1");
12             Console.WriteLine("主线程执行2");
13             methord.BeginInvoke("demo-ok", null, null);
14             Console.WriteLine("主线程执行3");
15             Console.WriteLine("主线程执行4");
16             Console.ReadKey();
17         }
18         /// <summary>
19         /// 异步调用委托方法
20         /// </summary>
21         /// <param name="o"></param>
22         static void Test(string o)
23         {
24             Console.WriteLine("有参无返回值:{0}", o);
25         }
26         /*
27          * 作者:Jonins
28          * 出处:http://www.cnblogs.com/jonins/
29          */
30     }

因为调用BeginInvoke为异步委托,不会窒碍主线程,运转结果如下:

图片 1

 

2.寄托的概念

异步回调(Callback卡塔尔国

异步回调通过安装回调函数,当调用截止时会自动调用回调函数,能够在回调函数里触发EndInvoke,那样就释放掉了线程,可以制止程序一贯攻下二个线程。

 1     class Program
 2     {
 3         /// <summary>
 4         /// 定义有参有返回值委托
 5         /// </summary>
 6         /// <param name="i"></param>
 7         public delegate string ReturnWithParameters(string o);
 8         static void Main(string[] args)
 9         {
10             ReturnWithParameters methord = new ReturnWithParameters(Test);
11             Console.WriteLine("主线程执行1");
12             Console.WriteLine("主线程执行2");
13             /*
14              BeginInvoke方法参数个数不确定, 最后两个参数含义固定,如果不使用的话,需要赋值null
15              委托的方法无参数,这种情况下BeginInvoke中只有两个参数。
16              此外,委托的方法有几个参数,BeginInvoke中从左开始,对应响应的参数。
17              1.倒数第二个参数:是有一个参数值无返回值的委托,它代表的含义为,该线程执行完毕后的回调。
18              2.倒数第一个参数:向即回调中传值,用AsyncState来接受。
19              3.其它参数:对应委托方法的参数。
20              */
21             IAsyncResult asyncResult = methord.BeginInvoke("demo-ok", new AsyncCallback(Callback), "AsycState:给回调函数的参数传递在此处出传值");
22             Console.WriteLine("主线程执行3");
23             Console.WriteLine("主线程执行4");
24             Console.ReadKey();
25         }
26         /// <summary>
27         /// 异步调用委托方法
28         /// </summary>
29         /// <param name="o"></param>
30         /// <returns></returns>
31         private static string Test(string o)
32         {
33             return "委托方法执行成功:" + o;
34         }
35         /// <summary>
36         /// 回调函数
37         /// </summary>
38         /// <param name="asyncResult"></param>
39         private static void Callback(IAsyncResult asyncResult)
40         {
41             /*
42              *asyncResult为回调前异步调用方法返回值
43              *AsyncResult 是IAsyncResult接口的一个实现类,引用空间:System.Runtime.Remoting.Messaging
44              *AsyncDelegate 属性可以强制转换为定义的委托类型
45              */
46             ReturnWithParameters methord = (ReturnWithParameters)((System.Runtime.Remoting.Messaging.AsyncResult)asyncResult).AsyncDelegate;
47             Console.WriteLine(methord.EndInvoke(asyncResult));
48             Console.WriteLine(asyncResult.AsyncState);
49         }
50         /*
51          * 作者:Jonins
52          * 出处:http://www.cnblogs.com/jonins/
53          */
54     }

实践结果如下:

图片 2

注意:

1.异步调用只可以调用一回EndInvoke,不然会报错。

2.比方不回调函数中试行EndInvoke,请在异步调用后手动施行EndInvoke方法释放能源。

 

delegate int Add(int num1,int
num2);

异步委托线程等待 

1.【Delegate】.EndInvoke(推荐)

1   public delegate void NoReturnWithParameters(string o);
2   NoReturnWithParameters noReturnWithParameters = new NoReturnWithParameters(...);
3        ......
4   noReturnWithParameters.EndInvoke(asyncResult);

2.【IAsyncResult】.AsyncWaitHandle.WaitOne(能够定义等待时间,抢先等待时间不一而再三番五次守候向下举行卡塔尔国

1  IAsyncResult asyncResult = null;
2  asyncResult.AsyncWaitHandle.WaitOne(2000);//等待2000毫秒,超时不等待

3.【IAsyncResult】.IsCompleted(是IAsyncResult对象的二个性能,该值提醒异步操作是还是不是已成功。不推荐卡塔 尔(阿拉伯语:قطر‎

1  IAsyncResult asyncResult = xxx.BeginInvoke(...);
2  while (!asyncResult.IsCompleted)
3  {
4      //正在等待中
5  }

 

delegate void ConvertNum(string
result);

内置委托(泛化委托卡塔 尔(英语:State of Qatar)

 .Net Framework 提供八个帮衬泛型的放到委托,分别是Action<>Func<>,在System命名空间中定义,结合lambda表明式,能够巩固开销功用。

图片 3图片 4

运用办法如下:

 1     class Program
 2     {
 3         static void Main(string[] args)
 4         {
 5             //使用Action声明委托
 6             Action<string> action = TestAction;
 7             action.Invoke("action-demo-ok");
 8             //使用Func声明委托
 9             Func<string, string> func = TestFunc;
10             string result = func.Invoke("func-demo-ok");
11             Console.WriteLine(result);
12             Console.ReadKey();
13         }
14         private static void TestAction(string o)
15         {
16             Console.WriteLine("TestAction方法执行成功:{0}", o);
17         }
18         private static string TestFunc(string o)
19         {
20             return "TestFunc方法执行成功:" + o;
21         }
22         /*
23          * 作者:Jonins
24          * 出处:http://www.cnblogs.com/jonins/
25          */
26     }

Action:无再次回到值的泛型委托,方今.NET Framework提供了14个Action信托,它们从无参数到最多十四个参数。

public delegate void Action

Action

无重返值的泛型委托

Action<int,string>

盛传参数int、string,无再次回到值的委托

Action<int,string,bool> 

传扬参数int,string,bool,无再次来到值的寄托

Action<bool,bool,bool,bool> 

流传4个bool型参数,无再次回到值的嘱托

Action起码0个参数,最多十四个参数,无重返值。

 

 

 

 

 

Func:有重临值的泛型委托,.NET
Framework提供了14个Func函数,允许回调方法再次回到值。

public delegate TResult Func

Func<int> 

无参,再次回到值为int的委托

Func<int,string>

传扬参数int,重回值为string类型的寄托

Func<object,string,bool> 

流传参数为object, string 再次回到值为bool类型的信托

Func<T1,T2,,T3,int> 表示

传播参数为T1,T2,,T3(类型)再次回到值为int类型的嘱托

Func起码0个参数,最多14个参数,依照重临值泛型再次回到。必须有再次来到值,不可为void。

 

 

 

 

 

本质上ActionFunc都为delegate ,在System命名空间中定义(in和out用来标志变量卡塔尔国

图片 5

除此而外还应该有Predicate,它是固定再次来到值为bool类型的泛型委托。Action和Func丰盛使用这里不做牵线。

注意:

1.委托定义不要太多,微软仅在MSCorLib.dll中就有进肆十五个委托项目,况兼.NET
Framework今后扶持泛型,所以我们只需多少个泛型委托(在System命名空间中定义)就会表示须求得到多达十多少个参数的法子。

2.如需拿到十六个以上参数,就必须要定义自己的信托项目。所以提出尽量利用内置委托,并不是在代码中定义越来越多的委托项目,那样能够减去代码中的类型数量,同一时候简化编码。

3.如需利用ref或out关键字以传援引的措施传递参数,就要求定义本身的寄托。

 

下边是概念五个委托的事例,其实很简单。声Bellamy(Bellamy卡塔 尔(阿拉伯语:قطر‎个信托行使delegate关键字,上边分别是概念的带重回值的嘱托和不带重回值的信托, 

嵌入委托(泛化委托卡塔尔国参数协变&逆变

协变(out):假定S是B的子类,假使X(S)允许援引转变到X(B),那么称X为协变类。(帮助“子类”向“父类”调换卡塔 尔(阿拉伯语:قطر‎
逆变(in):假定S是B的子类,借使X(B)允许援用调换来X(X),那么称X为协变类。(援救“父类”向“子类”转换卡塔 尔(阿拉伯语:قطر‎

正如泛化接口,泛型委托同一支撑协变与逆变

1     public delegate void Action<in T>(T obj);
2    
3     public delegate TResult Func<out TResult>();

Action在System命名空间中定义协理逆变(in)

1         Action<object> x =...;
2         
3         Action<string> y = x;    

Func在System命名空间中定义帮助协变(out)

1         Func<string> x =...;
2             
3         Func<object> y = x; 

假诺要定义八个泛化委托项目,最佳依照如下法规:
1.将只用在重临值的项目参数评释为协变(out卡塔 尔(英语:State of Qatar)
2.将只用在参数的档期的顺序参数标明为逆变(in卡塔尔国

五个委托都有传递参数,当然也能够不传递参数。其实委托也是三个类,委托洛茨基派生为System.MulticastDelegate,而System.MulticastDelegate

信托的包容性

刺探委托的包容性,更便于在行使委托时使大家创设的代码具备多态性

1.类型的宽容性:即便签字相近,委托类也互不宽容。

1 delegate void D1();
2 delegate void D2();
3 ...
4 D1 d1=Method1;
5 D2 d2=d1;//编译时错误
6 D2 d2=new D2(d1);//这是允许的

大器晚成经委托实例试行相符的指标措施,则以为它们是等价的。

1 delegate void D();
2 ...
3 D1 d1=Method1;
4 D2 d2=Method1;
5 Console.WriteLine(d1==d2);//True

倘诺多播委托根据相近的顺序应用相符的法门义务委托它们是等价的。

2.参数的包容性:当调用三个措施时,能够给艺术的参数提供超过其钦命项指标变量。那是例行的多态行为。相同,委托也足以又当先其目的措施参数类型的参数,即逆变。

 1     class Program
 2     {
 3         //委托接受string类型参数
 4         delegate void NoReturnWithParameters(string o);
 5         static void Main(string[] args)
 6         {
 7             NoReturnWithParameters noReturnWithParameters = new NoReturnWithParameters(Test);
 8             noReturnWithParameters("demo-ok");
 9             Console.ReadKey();
10         }
11         //目标方法接受object类型参数
12         static void Test(object o)
13         {
14             Console.WriteLine("返回值:{0}", o);
15         }
16     }

上述代码将参数string在调用指标措施时隐式向上转换为Object。

3.回去类型的宽容性:要是调用三个艺术,获得的回来值类型或然超乎乞请的档案的次序,那是健康多态行为。相通,寄托的归来类型能够低于它的对象措施的归来值类型即协变**。**

 1     class Program
 2     {
 3         //委托返回object类型
 4         delegate object NoReturnWithParameters(string o);
 5         static void Main(string[] args)
 6         {
 7             NoReturnWithParameters noReturnWithParameters = new NoReturnWithParameters(Test);
 8             object o = noReturnWithParameters("demo-ok");
 9             Console.WriteLine(o);
10             Console.ReadKey();
11         }
12         //目标方法返回string类型
13         static string Test(string o)
14         {
15             return "返回值:" + o;
16         }
17     }

注意:正式事件方式的宏图主题时再其利用国有基类EventArgs时使用逆变。比方,能够用多个不相同的嘱托调用同一个艺术,贰个传递Mouse伊夫ntArgs,另一个传递Key伊夫ntArgs。

 

又持续System.Delegate,假诺您知道那一个也就知晓委托其实是三个风格迥异的类。

多播委托(+=&-=卡塔尔国

拥有的嘱托的实例都有多播的功能,自定义委托和停放委托皆有,能够由此+=-=给委托扩张和删掉分化的格局,当输入参数后,各种方法会按顺序进行迭代管理,并回到尾数方式的精打细算结果。上边是轻巧模拟总结器的大器晚成段代码:

 1     class Program
 2     {
 3         public delegate int MulticastInstance(int inputA, int inputB);
 4         static void Main(string[] args)
 5         {
 6             MulticastInstance multicastInstance = Addition;
 7             multicastInstance += new MulticastInstance(Reduce);
 8             multicastInstance += new MulticastInstance(Multiply);
 9             int result = multicastInstance(10, 5);
10             Console.WriteLine("最后执行得到的结果为:{0}", result);
11             Console.ReadKey();
12         }
13         /// <summary>
14         /// 加法
15         /// </summary>
16         /// <param name="inputA"></param>
17         /// <param name="inputB"></param>
18         /// <returns></returns>
19         private static int Addition(int inputA, int inputB)
20         {
21             int result = inputA + inputB;
22             Console.WriteLine("Addition方法执行结果:{0}", result);
23             return result;
24         }
25         /// <summary>
26         /// 减法
27         /// </summary>
28         /// <param name="inputA"></param>
29         /// <param name="inputB"></param>
30         /// <returns></returns>
31         private static int Reduce(int inputA, int inputB)
32         {
33             int result = inputA - inputB;
34             Console.WriteLine("Reduce方法执行结果:{0}", result);
35             return result;
36         }
37         /// <summary>
38         /// 乘法
39         /// </summary>
40         /// <param name="inputA"></param>
41         /// <param name="inputB"></param>
42         /// <returns></returns>
43         private static int Multiply(int inputA, int inputB)
44         {
45             int result = inputA * inputB;
46             Console.WriteLine("Multiply方法执行结果:{0}", result);
47             return result;
48         }
49         /*
50          * 作者:Jonins
51          * 出处:http://www.cnblogs.com/jonins/
52          */
53     }

赢得的结果如下:

图片 6

多播委托本质是:委托是不可变的,由此调用+=或-=的本质是创制二个新的委托实例,并把它赋值给本来就有变量。全数的嘱托项目都是从System.MulticastDelegate派生的,它又持续自System.Delegate,c#将委托中采纳的+、-、+=、-=都编写翻译成System.Delegate的静态CombineRemove方法。

 

 

信托模拟观望者

能用委托撤废的标题,都得以用接口化解。但再下边包车型地铁情况中,委托大概是比接口更加好的筛选:

1.接口内之定义二个措施

2.内需多播工夫

3.订阅者供给反复兑现接口

上面代码是信托的观望者情势,优点是解耦且切合开放密封原则:

 1 public class MulticastDelegates
 2 {
 3     public delegate int MulticastInstance(int inputA, int inputB);
 4     /// <summary>
 5     /// 模拟观察者
 6     /// </summary>
 7     public void Demo()
 8     {
 9         Manager manager = new Manager();
10         manager.Attach(new MulticastInstance(Add));
11         manager.Attach(new MulticastInstance(Reduce));
12         manager.Attach(new MulticastInstance(Multiply));
13         manager.Execute(10, 5);
14     }
15     /// <summary>
16     /// Observer模式、又称呼发布订阅或监听模式
17     /// </summary>
18     public class Manager
19     {
20         private MulticastInstance Handler;
21 
22         /// <summary>
23         /// 附加观察者
24         /// </summary>
25         /// <param name="handler1"></param>
26         public void Attach(MulticastInstance handler1)
27         {
28             Handler += handler1;
29         }
30         /// <summary>
31         /// 分离观察者
32         /// </summary>
33         /// <param name="handler1"></param>
34         public void Detach(MulticastInstance handler1)
35         {
36             Handler -= handler1;
37         }
38         /// <summary>
39         /// 如果观察者数量大于0即执行播委托列表中的方法
40         /// </summary>
41         /// <param name="inputA"></param>
42         /// <param name="inputB"></param>
43         public void Execute(int inputA, int inputB)
44         {
45             if (Handler != null)
46                 if (Handler.GetInvocationList().Count() != 0)
47                     Handler(inputA, inputB);
48         }
49     }
50     private int Add(int inputA, int inputB)
51     {
52         int result = inputA + inputB;
53         Console.WriteLine("Add方法执行结果:{0}", result);
54         return result;
55     }
56     private int Reduce(int inputA, int inputB)
57     {
58         int result = inputA - inputB;
59         Console.WriteLine("Reduce方法执行结果:{0}", result);
60         return result;
61     }
62     private int Multiply(int inputA, int inputB)
63     {
64         int result = inputA * inputB;
65         Console.WriteLine("Multiply方法执行结果:{0}", result);
66         return result;
67     }
68 }

 

图片 7图片 8

寄托揭秘

信托看似相当轻便采用,通过delegate根本词定义,用通晓的new协会委托实例,领悟的主意调用回调函数,但实质上编译器和CL普拉多在暗地里做了汪洋职业来掩瞒其复杂性。

重复审视上边总结器的生机勃勃段代码:

1     public delegate int MulticastInstance(int inputA, int inputB);

实际上通过反编写翻译可观望:

图片 9

编写翻译器相当于概念了多个风流倜傥体化的类(继承自System.MulticastDelegate,定义七个艺术:构造函数、Invoke、BeginInvoke和EndInvoke卡塔尔国:

 

 1      internal class MulticastInstance : System.MulticastDelegate//继承System.MulticastDelegate
 2         {
 3             //构造器
 4             public MulticastInstance(object @object, IntPtr method);
 5             //这个方法的原型和源代码指定的一样
 6             public virtual int Invoke(int inputA, int inputB);
 7             //实现回调方法和异步回调
 8             public virtual IAsyncResult BeginInvoke(int inputA, int inputB, AsyncCallback callback, object @object);
 9             public virtual int EndInvoke(IAsyncResult result);
10         }
11         /*
12          * 作者:Jonins
13          * 出处:http://www.cnblogs.com/jonins/
14          */

所有信托项目都派生自System.MulticastDelegate类,System.MulticastDelegate派生自System.Delegate,前面一个又派生自System.Object。历史由来促成有三个委托类。
始建的享有寄托项目豆奶MulticastDelegate作为基类,个别情形下仍会用到Delegate。Delegate类的四个静态方法CombineRemove的签字都提议要博取Delegate参数。由于创设的信托项目派生自MulticastDelegate,前者又派生自Delegate,所以委托项指标实例是能够传递给那四个方法的。

MulticastDelegate的四个器重非公共字段

字段 类型 说明
_target System.Object

当委托对象包装一个静态方法时,这个字段为null。当委托对象包装一个实例方法时,这个字段引用的是回调方法要操作的对象。

当委托对象包装一个实例方法时,这个字段引用的是回调方法要操作的对象。换言之

换言之,这个字段指出要传给实例方法的隐士参数的值。

_methodPtr System.IntPtr

一个内部的整数值,CLR用它标记要回调的方法。

_invocationList System.Object 该字段通常为null,构造委托链时它引用一个委托数组。

Delegate反编译后可观望静态方法CombineRemove(委托的+、-、+=、-=编写翻译后的实质卡塔尔国:

 1     [Serializable, ClassInterface(ClassInterfaceType.AutoDual), ComVisible(true), __DynamicallyInvokable]
 2     public abstract class Delegate : ICloneable, ISerializable
 3     {
 4         [ComVisible(true), __DynamicallyInvokable]
 5         public static Delegate Combine(params Delegate[] delegates);
 6         [__DynamicallyInvokable]
 7         public static Delegate Combine(Delegate a, Delegate b);
 8         [SecuritySafeCritical, __DynamicallyInvokable]
 9         public static Delegate Remove(Delegate source, Delegate value);
10     }

 

委托的简单实用例子Code highlighting produced by Actipro CodeHighlighter (freeware)http://www.CodeHighlighter.com/--> 1 public delegate string TeaDelegate(string spText);

    public class DelegateSource
    {
        public void TestDelegate()
        {
            Operator op = new Operator();
            TeaDelegate tea = new TeaDelegate(op.GetTea);
            Console.WriteLine("去给我倒杯水");
            Console.WriteLine();
            string result=tea("去给我倒杯水");
            Thread.Sleep(5000);
            Console.WriteLine(result);
            Console.WriteLine();
        }
    }

    public class Operator
    {
        /// <summary>
        /// 确定是否还有水
        /// </summary>
        private bool flag = true;

        public string GetTea(string spText)
        {
            if (spText == "去给我倒杯水")
            {
                if (flag)
                {
                    return "老公,茶来了";
                }
                else
                {
                    return "老公,没有水了";
                }
            }
            return "等待.......";
        }
    }

 结语

协同委托将梗塞当前线程,等待方法实行落成继续执路程序,相当于直接调用方法。异步委托是将艺术归入线程池中举行并不打断主线程。异步委托从根本上说并不是三十二线程才干(任务Task也如出意气风发辙卡塔 尔(英语:State of Qatar),就算异步委托内部将艺术塞给线程池去实施也并不能够算得开垦新线程施行措施,(线程池一定开荒新线程卡塔 尔(英语:State of Qatar)这种说法并不行事极为谨严。信Torben质是将调用者和指标措施动态关联起来,那是唯恐是自己所领会的嘱托存在的最根本指标呢。

 

View Code

仿照效法文献

CLR via C#(第4版) Jeffrey Richter

C#高级编制程序(第7版卡塔 尔(英语:State of Qatar) Christian Nagel

果壳中的C# C#5.0高于指南 Joseph Albahari

……


 

输出结果

图片 10 

地点运用最家常的后生可畏种情势来定义了叁个委托的施用,那么些事例即便很简短,不过能够很形象的陈诉委托的行使。

3.寄托的二种情势

(1).推断

图片 11图片 12

推断委托例子Code highlighting produced by Actipro CodeHighlighter (freeware)http://www.CodeHighlighter.com/--> 1 public delegate string TeaDelegate(string spText);

    public class DelegateSource
    {
        public void TestDelegate()
        {
            Operator op = new Operator();
            TeaDelegate tea = op.GetTea;
            Console.WriteLine("去给我倒杯水");
            Console.WriteLine();
            string result=tea("去给我倒杯水");
            Thread.Sleep(5000);
            Console.WriteLine(result);
            Console.WriteLine();
        }
    }

    public class Operator
    {
        /// <summary>
        /// 确定是否还有水
        /// </summary>
        private bool flag = true;

        public string GetTea(string spText)
        {
            if (spText == "去给我倒杯水")
            {
                if (flag)
                {
                    return "老公,茶来了";
                }
                else
                {
                    return "老公,没有水了";
                }
            }
            return "等待.......";
        }
    }

View Code

在信托定义的例证中大家看出委托的运用方法是在信托实例化的时候钦赐的[new
DelegateName(FunctionName)],这里大概表述不是太然则代码应该看得白了。
而委托的估摸,并未new 委托这么些手续,而是径直将Function 钦定给委托。

 (2).佚名函数

图片 13图片 14

匿名委托例子Code highlighting produced by Actipro CodeHighlighter (freeware)http://www.CodeHighlighter.com/--> 1 public delegate string TeaDelegate(string spText);

    public class DelegateSource
    {
        public void TestDelegate()
        {
            Operator op = new Operator();
            bool flag = true;
            TeaDelegate tea = delegate(string spText)
            {
                if (spText == "去给我倒杯水")
                {
                    if (flag)
                    {
                        return "老公,茶来了";
                    }
                    else
                    {
                        return "老公,没有水了";
                    }
                }
                return "等待.......";
            };

            Console.WriteLine("去给我倒杯水");
            Console.WriteLine();
            string result=tea("去给我倒杯水");
            Thread.Sleep(5000);
            Console.WriteLine(result);
            Console.WriteLine();
        }
    }

View Code

关于无名氏委托,给人的认为更是直接了,都无须展现的内定方法名,因为平昔无法,而是钦定的匿超级模特式。佚名格局在.NET
中拉长了 

代码的可读性和高雅性。对于愈来愈多操作相当少的秘籍间接写为无名函数,那样会大大进步代码的可读性。这里有多个值得注意的地点:
第豆蔻年华,无法运用

跳转语句跳转到该匿超级模特式外,第二
无法应用ref,out修饰的参数

(3).多播委托

图片 15图片 16

多播委托例子Code highlighting produced by Actipro CodeHighlighter (freeware)http://www.CodeHighlighter.com/--> 1 public delegate string TeaDelegate(string spText);

    public class DelegateSource
    {
        public void TestDelegate()
        {
            Operator op = new Operator();

            TeaDelegate tea1 = op.GetTea;
            TeaDelegate tea2 = op.Speak;
            TeaDelegate tea = tea1 + tea2;

            Console.WriteLine("去给我倒杯水");
            Console.WriteLine();
            string result=tea("去给我倒杯水");
            Thread.Sleep(5000);
            Console.WriteLine(result);
            Console.WriteLine();
        }
    }

    public class Operator
    {
        /// <summary>
        /// 确定是否还有水
        /// </summary>
        private bool flag = true;

        public string GetTea(string spText)
        {
            if (spText == "去给我倒杯水")
            {
                if (flag)
                {
                    return "老公,茶来了";
                }
                else
                {
                    return "老公,没有水了";
                }
            }
            return "等待.......";
        }


        public string Speak(string spText)
        {
            Console.WriteLine("\n去把我的设计图稿拿来");
            return null;
        }
    }

View Code

要么地点的老大实例,作者不尽想让女对象去给自身掉杯水,还让他帮我将顺序设计图稿拿过来。那时候做的就不是豆蔻年华件事了,而是多件。

次第中也可能有过多这种情状,于是大家供给多播委托,在叁个信托上点名多个推行形式,那是在前后相继中能够行的。下面提到了,委托直接接轨于

System.MulticastDelegate,正是因为那几个类能够完成多播委托。若是调用多播委托,就足以按顺序一连调用八个措施。为此,委托的具名就必需回到void;不然,就一定要得到委托调用的末尾一个主意的结果。所以在上边的这段代码中是得不到结果的

 

4.事件

使用C#编制程序,无论是WinForm,WebForm
给人很难忘得就是它的控件,而她们的控件库使用方法都以使用使用事件驱动格局,而事件驱动格局却少不了委托。话不多说,看代码能够更清好的接头事件和委托时期的联系. 

图片 17图片 18

发表评论

电子邮件地址不会被公开。 必填项已用*标注