委托学习,框架结构的血流

本篇小说重要介绍委托的施用。

标签(空格分隔): C#


Delegate Predicate Action Func逆变和协变

信托是大家最常见的语法了,但会用与通晓之间的差异是铁汉的。


 

委托学习,框架结构的血流。  先说下哪些是信托(Delegate),委托在C#中是一种档次,和Class是2个级别,然则大家平日把它看作是一个格局。为何是措施?准确的说应该是回调函数,在C运转时的qsort函数获取指向三个回调函数的指针,以便对数组中的成分进行排序。C#中提供了一种体制,正是信托,一种回调函数的建制

1个程序员借使无法精晓委托,那么,他永远无法成为高档程序员。

看马克down效果帮助的一点都不大好。

寄托概述

将艺术调用者和指标措施动态关联起来,委托是多个类,所以它和类是同级的,能够通过信托来掉用艺术,不要误以为委托和格局同级的,方法只是类的分子。委托定义了点子的花色(定义委托和与之相应的格局必须具备相同的参数个数,并且类型相同,重临值类型相同),使得可以将艺术当作另贰个情势的参数来展开传递,那种将艺术动态地赋给参数的做法,可避防止在先后中山高校量施用If-Else(Switch)语句,同时使得程序有所更好的可扩大性。

 

  在大家做项指标长河中,委托用到的地方重重,像线程中期维修改窗体的气象、窗体控件事件和异步操作已成功等,在此以前我们创设委托的时候用delegate关键字,而且也正如劳顿,自从C#4.0有了泛型,也就有了泛型委托,使用Predicate、Action和Func大家得以更好的成立委托。

故而,让我们把委托刻到血液里吗。

买来《CLR Via
C#》那本书很久了,一直也从未对其进行总计,看的分外混乱,趁此机会好好总计一下,也算对C#学习的2个计算。

基础委托(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     }

 

Delegate

  我们原先定义一个寄托能够如此:

01.``1         delegate Boolean delgate1(``int
item);

02.`` ``2         public void
delgateCommon()

03.`` ``3         {

04.`` ``4             var d1 = ``new
delgate1(delegateMethod1);

05.`` ``5             if
(d1(``1``))

06.`` ``6             {

07.`` ``7

08.`` ``8             }

09.`` ``9         }

10.``10         static
bool delegateMethod1(``int item)

11.``11         {

12.``12             return
false``;

13.``13         }

  通过地方简单的以身作则可以观看,先成立三个delgate1的信托项目,参数类型是int,重回值时bool,上面定义2个静态方法delegateMethod1,创设一个delgate1类型的实例,参数为delegateMethod1方法名,这一个也改为订阅或是注册,为这么些委托项目注册多少个回调方法,上边就是调用了,大家在C#成立调用二个委托正是这么简单,其实是很复杂的,只可是这几个工作是编写翻译器帮我们做了。

  必要专注的是地方定义的回调方法是静态(static),假若大家成立的不是静态方法,也是足以,只可是调用的时候要求实例访问。

  静态方法都以通过首要字static来定义的,静态方法不须要实例这么些指标就能够透过类名来访问这一个目的。在静态方法中不能够一向访问类中的非静态成员。而用实例方法则供给经过切实的实例对象来调用,并且能够访问实例对象中的任何成员。假诺用委托绑定实例方法的话供给用实例对象来拜会,所以我们在绑定实例方法到委托的时
候必须同时让委托获得实例对象的音信,那样才能在委托被回调的时候成功推行这些实例方法。也正是说,当绑定实例方法给委托的时候,参数会被安装为这几个参数所在项指标实例对象。假若给委托绑定的是静态方法,那么这几个参数将被设置为NULL。

  综上,委托既能够绑定静态方法也得以绑定实例方法,但是在绑定实例方法的时候,delegate的target属性就被设置为指向那些实例方法所属种类的2个实例对象。当绑定静态方法时,delegate的target属性就给NULL。

  废话说的有个别多,下边大家看下C#泛型委托,和组合一些匿名函数,lambda表明式的采纳,其实正是有个别出奇的委托。

那般,你才能称之为[Developer]。

  • 初识委托
  • 用委托回调方法
  • 泛型委托
  • 简化语法

共同委托&异步委托

一道委托:委托的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

 

Predicate

 

01.``1     // 摘要:

02.`` ``2    
//     表示定义一组条件并确定指定对象是否符合这些条件的方法。

03.`` ``3     //

04.`` ``4     // 参数:

05.`` ``5     //   obj:

06.`` ``6    
//     要按照由此委托表示的方法中定义的条件进行比较的对象。

07.`` ``7     //

08.`` ``8     // 类型参数:

09.`` ``9     //   T:

10.``10    
//     要比较的对象的类型。

11.``11     //

12.``12     // 返回结果:

13.``13    
//     如果 obj 符合由此委托表示的方法中定义的条件,则为 true;否则为 false。

14.``14     public
delegate bool Predicate<in T>(T obj);

  能够看出Predicate的签字是3个泛型参数,重回值是bool。须要留意的是T前边的in表示什么意思?请点那里。代码能够这样写:

 

01.``1         public void
delgatePredicate()

02.`` ``2         {

03.`` ``3             var d1 = ``new
Predicate<``int``>(delegateMethod2);

04.`` ``4             if
(d1(``1``))

05.`` ``5             {

06.`` ``6

07.`` ``7             }

08.`` ``8         }

09.`` ``9         static
bool delegateMethod2(``int item)

10.``10         {

11.``11             return
false``;

12.``12         }

  能够看到使用Predicate创立委托简化了许多,大家得以自定义参数,但是只可以有一个,而且再次来到值必须是bool类型,是或不是深感限制太多了?无再次来到值或是四个参数如何是好?请看下边。

委托的定义

初识委托

信托类型 (delegate type)
表示对具有特定参数列表和返回类型的方法的引用(个人认为那句话对信托的表明相当好)。通过信托,大家能够将艺术作为实体赋值给变量和作为参数字传送递。委托类似于在其余一些语言中的函数指针的定义。.NET Framework通过委托来提供回调函数机制,委托保管了回调函数是类型安全的。
调用二个委托的法门:

  1. 声称3个寄托项目
  2. 宣示二个办法包括要履行的代码
  3. 始建3个信托实例
  4. 调用这一个委托实例

异步回调(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方法释放资源。

 

Action

 

01.``1     // 摘要:

02.`` ``2    
//     封装一个方法,该方法具有两个参数并且不返回值。

03.`` ``3     //

04.`` ``4     // 参数:

05.`` ``5     //   arg1:

06.`` ``6    
//     此委托封装的方法的第一个参数。

07.`` ``7     //

08.`` ``8     //   arg2:

09.`` ``9    
//     此委托封装的方法的第二个参数。

10.``10     //

11.``11     // 类型参数:

12.``12     //   T1:

13.``13    
//     此委托封装的方法的第一个参数类型。

14.``14     //

15.``15     //   T2:

16.``16    
//     此委托封装的方法的第二个参数类型。

17.``17    
[TypeForwardedFrom(``"System.Core, Version=3.5.0.0, Culture=Neutral, PublicKeyToken=b77a5c561934e089"``)]

18.``18     public delegate ``void
Action<in T1, in T2>(T1 arg1, T2 arg2);

  上面是Action四个泛型参数的签订契约,最多帮衬十四个泛型参数,能够看来Action无再次来到值,创立代码如下:

 

01.``1         public void
delgateAction()

02.`` ``2         {

03.`` ``3             var d1 = ``new
Action<``int``>(delegateMethod3);

04.`` ``4             var d2 = ``new
Action<``int``, string>(delegateMethod4);

05.`` ``5             d1(``1``);

06.`` ``6            
d2(``1``, ``""``);

07.`` ``7         }

08.`` ``8         static void
delegateMethod3(``int item)

09.`` ``9         {

10.``10         }

11.``11         static void
delegateMethod4(``int item, string str)

12.``12         {

13.``13         }

  若是大家想创制的信托项目是有五个参数,而且必需求有再次来到值,我们如何是好?请看上边。

什么是委托?

用委托回调方法

//1、声明一个委托实例
internal sealed class DelegateIntro {
    internal delegate void Feedback(Int32 value);
    private static void StaticDelegateDemo() {
          Console.WriteLine("----- Static Delegate Demo -----");
          //传递的为NUll,处理每个数据项都不调用回调方法
          Counter(1, 3, null);
          //3、创建静态的委托实例,用委托回调静态方法
          Counter(1, 3, new Feedback(DelegateIntro.FeedbackToConsole));
          Counter(1, 3, new Feedback(FeedbackToMsgBox)); // "Program." is optional
          Console.WriteLine();
       }

    private static void InstanceDelegateDemo() {
          Console.WriteLine("----- Instance Delegate Demo -----");
          //3、创建实例委托,用委托回调实例方法
          DelegateIntro di = new DelegateIntro();
          Counter(1, 3, new Feedback(di.FeedbackToFile));

          Console.WriteLine();
       }

    private static void Counter(Int32 from, Int32 to, Feedback fb)     {
          for (Int32 val = from; val <= to; val++) {
             // If any callbacks are specified, call them
             if (fb != null)
             //4、调用这个委托
                fb(val);
          }
       }
    //2、声明一个方法包含要执行的代码
    private static void FeedbackToConsole(Int32 value) {
          Console.WriteLine("Item=" + value);
       }
    //2、声明一个方法包含要执行的代码
    private static void FeedbackToMsgBox(Int32 value) {
          MessageBox.Show("Item=" + value);
       }

    private void FeedbackToFile(Int32 value) {
          StreamWriter sw = new StreamWriter("Status", true);
          sw.WriteLine("Item=" + value);
          sw.Close();
       }
}

信托对象是方法的包装器(wrapper),是办法能经过包装器来间接回调。如上的FeedbackToConsoleFeedbackToMsgBox方法通过委托包装,通过Counter主意来直接回调。
其一例子中的全体操作都以体系安全的。例如:在协会Feedback委托对象时,编写翻译器确认保障FeedbackToConsoleFeedbackToMsgBox格局的签字包容于Feedback委托类型定义的签名。具体的说,多少个主意都要获取二个参数(2个int32),而且双方都熬有同一的归来类型(Void),将FeedbackToConsole的定义改为上边那样
private static Boolean FeedbackToCOnsole(string value){
···
}
C#编写翻译器将不会编写翻译以上代码,并告诉一下荒谬:

error CS0123:”FeedbackToConsole”的重载均与寄托”Feedback”不合营

将艺术绑定到委托时,C#和CLRAV4都同意引用类型的协变性逆变性协变性是指方法能回去从委托的回来类型派生的四个档次。逆变性是指方法得到的参数能够是寄托的参数类型的基类。
比如:

delegate object Mycallback(fileStream s);

一齐能够协会该委托类型的2个实例并绑定到独具以下原型的格局

String SomeMethod(Stream s);

在此间,SomeMethod的归来类型String派生自信托的回来类型(Object),那是协变性;SomeMethod的参数类型Stream是寄托的参数类型FileStream的基类,那是逆变性
留意唯有引用类型才支撑协变性和逆变性。

异步委托线程等待 

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对象的2个属性,该值提示异步操作是还是不是已做到。不引进)

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

 

Func

 

01.``1     // 摘要:

02.`` ``2    
//     封装一个具有两个参数并返回 TResult 参数指定的类型值的方法。

03.`` ``3     //

04.`` ``4     // 参数:

05.`` ``5     //   arg1:

06.`` ``6    
//     此委托封装的方法的第一个参数。

07.`` ``7     //

08.`` ``8     //   arg2:

09.`` ``9    
//     此委托封装的方法的第二个参数。

10.``10     //

11.``11     // 类型参数:

12.``12     //   T1:

13.``13    
//     此委托封装的方法的第一个参数类型。

14.``14     //

15.``15     //   T2:

16.``16    
//     此委托封装的方法的第二个参数类型。

17.``17     //

18.``18     //   TResult:

19.``19    
//     此委托封装的方法的返回值类型。

20.``20     //

21.``21     // 返回结果:

22.``22    
//     此委托封装的方法的返回值。

23.``23    
[TypeForwardedFrom(``"System.Core, Version=3.5.0.0, Culture=Neutral, PublicKeyToken=b77a5c561934e089"``)]

24.``24     public
delegate TResult Func<in T1, in T2, out TResult>(T1 arg1, T2 arg2);

  上面是Func三个参数,1个再次来到值的署名,和Action一样最多协理十五个重返值,唯一的不一致是Func扶助自定义重返值类型,也得以看出T一 、T2前修饰符是in,TResult前的修饰符是out,这么些下边有证实。创立调用代码:

 

01.``1         public void
delgateFunc()

02.`` ``2         {

03.`` ``3            
string hiddenMethodString = ``""``;

04.`` ``4             var d1 = ``new
Func<``int``, bool>(delegateMethod5);

05.`` ``5             var d2 = ``new
Func<``int``, string, string>(delegate(``int
item, string str)

06.`` ``6                 {

07.`` ``7                     return
hiddenMethodString;``//匿名方法,好处:可读性更好,可以访问当前上下文

08.`` ``8                 });

09.`` ``9             var d3 = ``new
Func<string, string>((a) => {

10.``10                 return
a;``//lambda表达式,a作为参数,自动判断类型,如果单条语句,省略{}

11.``11             });

12.``12             d1(``1``);

13.``13            
d2(``1``, ``""``);

14.``14             d3(``""``);

15.``15         }

16.``16         static
bool delegateMethod5(``int item)

17.``17         {

18.``18             return
true``;

19.``19         }

  上面包车型客车代码中大家应用和匿名方式和lambda表明式,能够看看当中的便宜,省略创制方法的进度,代码更简洁,在Func中动用lambda表明式是很广阔的,匿名格局有个便宜便是能够访问上下文中的变量,比如hiddenMethodString,关于匿名方式和lambda说明式在那就不做解读了,其实就是一种语法规范,随着C#的前行,也不止在进化转移中。

  完整示例代码:

亚洲必赢官网 3亚洲必赢官网 4

 

01.``1 using System;

02.`` ``2
using System.Collections.Generic;

03.`` ``3 using System.Linq;

04.`` ``4 using System.Text;

05.`` ``5

06.`` ``6
namespace Predicate_Action_Func

07.`` ``7 {

08.`` ``8     class Program

09.`` ``9     {

10.``10         static void
Main(string[] args)

11.``11         {

12.``12            
delgateCommon();

13.``13         }

14.``14

15.``15         #region 常规委托

16.``16         delegate Boolean delgate1(``int
item);

17.``17         public void
delgateCommon()

18.``18         {

19.``19             var d1 = ``new
delgate1(delegateMethod1);

20.``20             if
(d1(``1``))

21.``21             {

22.``22                
Console.WriteLine(``"111"``);

23.``23             }

24.``24         }

25.``25         bool delegateMethod1(``int
item)

26.``26         {

27.``27             return
true``;

28.``28         }

29.``29         #endregion

30.``30

31.``31        
#region Predicate委托-自定义参数(参数只能一个)

32.``32         public void
delgatePredicate()

33.``33         {

34.``34             var d1 = ``new
Predicate<``int``>(delegateMethod2);

35.``35             if
(d1(``1``))

36.``36             {

37.``37

38.``38             }

39.``39         }

40.``40         static
bool delegateMethod2(``int item)

41.``41         {

42.``42             return
false``;

43.``43         }

44.``44         #endregion

45.``45

46.``46        
#region Action委托-自定义参数(参数为多个,多类型,但无返回值)

47.``47         public void
delgateAction()

48.``48         {

49.``49             var d1 = ``new
Action<``int``>(delegateMethod3);

50.``50             var d2 = ``new
Action<``int``, string>(delegateMethod4);

51.``51             d1(``1``);

52.``52            
d2(``1``, ``""``);

53.``53         }

54.``54         static void
delegateMethod3(``int item)

55.``55         {

56.``56         }

57.``57         static void
delegateMethod4(``int item, string str)

58.``58         {

59.``59         }

60.``60         #endregion

61.``61

62.``62        
#region Func委托-自定义参数(参数为多个,多类型,但有返回值)

63.``63         public void
delgateFunc()

64.``64         {

65.``65            
string hiddenMethodString = ``""``;

66.``66             var d1 = ``new
Func<``int``, bool>(delegateMethod5);

67.``67             var d2 = ``new
Func<``int``, string, string>(delegate(``int
item, string str)

68.``68                 {

69.``69                     return
hiddenMethodString;``//匿名方法,好处:可读性更好,可以访问当前上下文

70.``70                 });

71.``71             var d3 = ``new
Func<string, string>((a) => {

72.``72                 return
a;``//lambda表达式,a作为参数,自动判断类型,如果单条语句,省略{}

73.``73             });

74.``74             d1(``1``);

75.``75            
d2(``1``, ``""``);

76.``76             d3(``""``);

77.``77         }

78.``78         static
bool delegateMethod5(``int item)

79.``79         {

80.``80             return
true``;

81.``81         }

82.``82         #endregion

83.``83     }

84.``84 }

View Code

委托实际上是一连串型,是一种引用类型。

泛型委托

.NET Framework今后支撑泛型,如重回void可用上边泛型

public delegate void Action();
public delegate void Action(T obj);
public delegate void Action(T1 arg1,T2 arg2);
public delegate void Action(T1 arg1,T2 arg2,T3 arg3);

实际,.NET
Framework未来提供了1九个Action寄托,它们从无参数到最多16个参数,使用起来尤其有利于。就算急需再次回到值,可选拔Func函数。假使须求采取ref或out关键字以传引用的办法传送参数,就须求团结定义委托了。

内置委托(泛化委托)

 .Net Framework 提供五个补助泛型的放到委托,分别是Action<>Func<>,在System命名空间中定义,结合lambda表明式,能够提升支付功效。

亚洲必赢官网 5亚洲必赢官网 6

应用格局如下:

 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提供了1多个Action寄托,它们从无参数到最多1四个参数。

public delegate void Action

Action

无重返值的泛型委托

Action<int,string>

传播参数int、string,无再次来到值的嘱托

Action<int,string,bool> 

盛传参数int,string,bool,无重返值的委托

Action<bool,bool,bool,bool> 

传扬七个bool型参数,无重回值的寄托

Action最少0个参数,最多十七个参数,无再次来到值。

 

 

 

 

 

Func:有重临值的泛型委托,.NET
Framework提供了1柒个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个参数,最多17个参数,依据重回值泛型重临。必须有再次来到值,不可为void。

 

 

 

 

 

本质上ActionFunc都为delegate ,在System命名空间中定义(in和out用来标识变量)

亚洲必赢官网 7

除开还有Predicate,它是固定重临值为bool类型的泛型委托。Action和Func丰盛使用那里不做牵线。

注意:

1.信托定义不要太多,微软仅在MSCorLib.dll中就有进肆18个委托项目,而且.NET
Framework未来扶助泛型,所以大家只需多少个泛型委托(在System命名空间中定义)就能表示须求得到多达拾伍个参数的办法。

2.如需取得1陆个以上参数,就非得定义本身的信托项目。所以提议尽可能使用内置委托,而不是在代码中定义越来越多的委托项目,那样能够缩小代码中的类型数量,同时简化编码。

3.如需利用ref或out关键字以传引用的不二法门传递参数,就须要定义自个儿的寄托。

 

逆变和协变

微软用delegate关键字来声称委托,delegate与int,string,double等根本字一样。都以声称用的。

简化语法

置于委托(泛化委托)参数协变&逆变

协变(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个泛化委托项目,最佳依照如下准则:
1.将只用在重回值的连串参数标注为协变(out)
2.将只用在参数的项目参数标注为逆变(in)

什么样是逆变性、协变性?

  我们这么创制和调用委托:

 

01.``1        
delegate object delgate1(FieldAccessException item);

02.`` ``2         public void
delgateCommon()

03.`` ``3         {

04.`` ``4             var d1 = ``new
delgate1(delegateMethod1);

05.`` ``5             Console.WriteLine(d1(``new
FieldAccessException()));

06.`` ``6         }

07.`` ``7         static
string delegateMethod1(Exception item)

08.`` ``8         {

09.`` ``9             return
"123"``;

10.``10         }

  能够看出有个别分歧了,参数和再次回到类型分歧,delegateMethod1的参数类型(Exception)是委托的参数类型(FieldAccessException)的基类,delegateMethod1的回来类型(String)派生自信托的回来类型(Object),那种正是逆变和协变,编译和平运动转是能够的,也正是说是被允许的,逆变和协变只好用来引用类型,不用用于值类型或void。

  逆变性:方法得到的参数能够是信托的参数类型的基类。

泛型类型参数能够从基类型更改为此类的派生类型
用in关键字标记逆变情势的花色参数
那几个参数一般作输入参数,那个在Predicate、Action中拥有展示

  协变性:方法能回到从委托的回来类型派生的三个连串。

泛型类型参数能够从派生类型变更为它的基类型

  • 用out关键字来标记协变形式的品类参数
  • 那个参数一般作为重返值,那几个在Func的TResult重返参数有所显示

      恐怕有点晕,只要记住逆变是指参数,协变是指重回值;逆变是指基类到派生类,协变是指派生类到基类。

    ### 怎么用逆变,协变?

      泛型委托Predicate、Action和Func都用到了逆变和协变,大家也能够不使用它们自定义一种泛型委托,如下:

    01.``1        
    delegate TResult MyDelegate<in T,out TResult>(T obj);

    02.`` ``2         public void
    delgateZidingyi()

    03.`` ``3         {

    04.`` ``4             var d1 = ``new
    MyDelegate<FieldAccessException, object>(delegateMethod6);

    05.`` ``5             d1(``new
    FieldAccessException());

    06.`` ``6         }

    07.`` ``7         static
    string delegateMethod6(Exception item)

    08.`` ``8         {

    09.`` ``9             return
    "123"``;

    10.``10         }

      其实下边定义的嘱托项目MyDelegate,也不供给创建那么麻烦,使用Func就可以了,也从中看到泛型委托Predicate、Action和Func只是微软方便大家创造委托提供的一种办法,大家一齐能够自定义,上面也认证了逆变和协变所起到的效能。

上面先看下声西楚码,这里注明了三个委托。

简化语法1:不要构造委托对象。

如:

ThreadPool.QueueUserWorkItem(SomeAsyncTask,5);

当然ThreadPool类的静态QueueUserWorkItem方法期待2个WaitCallback寄托对象的引用,但你未来直接能够传递多个措施符合waitCallback体系就能够了。但C#编写翻译器其实依旧会扭转waitcallback信托对象–只是语法简化了罢了。

寄托的包容性

精通委托的包容性,更便于在选取委托时使大家营造的代码具有多态性

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     }

注意:行业内部事件格局的安排宗旨时再其应用集体基类伊芙ntArgs时使用逆变。例如,能够用多个例外的委托调用同三个措施,二个传递Mouse伊夫ntArgs,另二个传递Key伊夫ntArgs。

 

public delegate void TestDelegate(string message);
public delegate int TestDelegate(MyType m, long num);

简化语法2:不需求定义回调方法(lambda表达式)

前方代码中,回调方法名称SomeAsyncTask传给ThreadPool的QueueUserWorkItem方法。倘若措施较为简单能够平昔写为:

ThreadPool.QueueUserWorkItem(obj=>Console.WriteLine(Obj),5);

编写翻译器在观察则个lambda表达式后会生成贰个匿名格局。新的语言专业提出开发人士多多使用lambda表达式语法。
书本中的用委托回调四个格局没有下结论,个人认为未来三个方法已经大半了,等精通的好了再去探讨调用多个法子。
文章另各州址:

多播委托(+=&-=)

富有的寄托的实例都有多播的效益,自定义委托和停放委托都有,能够经过+=-=给委托增添和删掉不一样的法子,当输入参数后,各类方法会按顺序举行迭代处理,并回到最终2个形式的估测计算结果。上面是简单模拟总括器的一段代码:

 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     }

赢得的结果如下:

亚洲必赢官网 8

多播委Torben质是:委托是不可变的,由此调用+=或-=的面目是开创叁个新的寄托实例,并把它赋值给已有变量。全部的委托项目都以从System.MulticastDelegate派生的,它又继续自System.Delegate,c#将委托中央银行使的+、-、+=、-=都编写翻译成System.Delegate的静态CombineRemove方法。

 

delegate既然是生死攸关字,和int,string一样,那么,为何delegate后又跟了1个void或然int呢?

信托模拟观看者

能用委托消除的标题,都得以用接口解决。但再下边包车型客车意况中,委托只怕是比接口更好的采取:

1.接口内之定义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 }

 

假使他们是如出一辙地位的主要字,为啥能够联手使用呢?

寄托揭秘

信托看似很不难选拔,通过delegate最首要词定义,用熟知的new结构委托实例,熟识的措施调用回调函数,但事实上编写翻译器和CL奥迪Q5在暗中做了大批量做事来隐藏其复杂性。

双重新审查视上边总计器的一段代码:

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     }

 

很简单,大家把delegate前边的 【void TestDelegate(string
message)】明白为2个变量,是还是不是就清晰明了了一些。

 结语

联手委托将卡住当前线程,等待方法执行达成继续执行程序,也就是直接调用方法。异步委托是将艺术放入线程池中推行并不封堵主线程。异步委托从根本上说并不是三十二线程技术(职责Task也一律),固然异步委托内部将艺术塞给线程池去实践也并不能够说是开辟新线程执行办法,(线程池一定开辟新线程)那种说法并不小心翼翼。寄托本质是将调用者和指标措施动态关联起来,那是可能是本身所精通的寄托存在的最根本指标吧。

 

咱俩把delegate关键字精晓为,是用来特别来定义那种复杂的变量的。而那种复杂的变量能够涵盖四个重临值和任意数目任意档次的流传参数。

参考文献

CLR via C#(第4版) Jeffrey Richter

C#尖端编制程序(第⑨版) Christian Nagel

果壳中的C# C#5.0权威指南 Joseph Albahari

……


 

有没有觉得,那么些复杂的变量尤其像多少个函数的定义。

正确,官方概念,委托项目标宣示与措施签名相似。所以,那些复杂变量,的确,书写的办法正是与函数一样。

那么,为啥这几个宣称方式如此怪异呢,是因为,大家用delegate定义的变量,只可以用函数赋值。赋值形式如下所示:

public delegate void TestDelegate(string message);
public delegate long TestDelegate2(int m, long num);
public static void Excute()
{
    TestDelegate2 td = Double; 
} 
static long Double(int m, long num)
{
    return m * num;
}

寄托的为主使用

学会了赋值以后,作者开头利用委托。

信托的利用办法如下:

string result = td(51, 8);
Console.WriteLine(result);

此处大家会发现,委托的运用办法与函数调用一样。

是的,它们确实是一致的。因为委托是用函数来赋值的,所以调用情势相同也并寻常,不是吧。

换一种说法,正是信托封装了1个函数。

假设委托是包裹的函数,并且它又是援引类型。那么委托第1种健康的选拔就披揭露来了。

那就是——引用类型的函数。

固然函数是引用类型,那么这么些函数只要没被内部存储器回收,就能够被调用。假使是public函数大概是public
static函数,那么它能跨越的东西就更加多了。

譬如说能够跨类调用,跨程序集调用等等。而那种用法,正是委托的大旨采纳。

匿名委托的运用

匿名委托的官方介绍:在 2.0 在此之前的 C#
版本中,证明委托的唯一方法是运用命名格局。 C# 2.0 引入匿名格局,在 C#
3.0 及更高版本中,Lambda 表明式取代匿超情势作为编写制定内联代码的首要选用办法。

看不懂没提到,咱们一贯来读书应用。代码如下:

delegate string anonymousDelegate(int m, long num);
public static void Excute()
{
    anonymousDelegate ad = delegate (int m, long num) { return m.ToString() + num.ToString(); };//2.0时代的匿名委托
    anonymousDelegate ad2 = (m, num) => { return m.ToString() + num.ToString(); };//3.0以后匿名委托 
}

如代码所示,匿名委托是拉姆da表达式,不懂的同校就当它是有定点写法即可,不用讲怎么着道理,只要记住并运用即可。

匿名委托尽管减少了少数代码,但依旧供给大家温馨去注明委托。全部,还是能再简写一点吧?

答案当然是,能够的。

Action与Func

Action与Func是微软为大家先行定义好了的,三个委托变量。在那之中Action是不带再次回到值的嘱托,Func是带重回值的信托。

能够说,Action与Func完全包蕴了,大家经常使用所需的,全体的,委托变量。

也正是说,大家能够毫无再去协调手动表明委托了。

上面来看最简便的Action与Func的概念:

Action a1 = () => { };
Func<int> f1 = () => { return 1; };//必须写 return 1;

Action与Func是泛型委托,各支持17个入参变量。下边代码为多少个入参的概念,多参数以此类推。

Action<int> a1 = (i) =>  { };
Func<string,int> f1 = (str) => {  return 1;//必须写 return 1; };

信托的线程应用

信托的线程应用是信托的第③种用法,分为线程使用委托,和委托的异步应用三种。

咱俩先看线程使用委托。如下代码所示,二个无入参匿名Action和三个无入参匿名Func。

Task taskAction = new Task(() => { });//无入参匿名Action
taskAction.Start(); 
Task<int> taskFunc = new Task<int>(() => { return 1; });//无入参匿名Func
taskFunc.Start();
int result= taskFunc.GetAwaiter().GetResult();//获取线程返回结果

咱俩能来看二种委托行使,代码都相当简洁。

上边咱们再来看委托的异步应用。首先看最简易的异步调用。

Action action = new Action(() => { });
IAsyncResult result = action.BeginInvoke((iar) =>
{
}, null);

Func<int> func = new Func<int>(() => { return 1; });  
IAsyncResult resultfunc = func.BeginInvoke((iar) =>
{
    var res = func.EndInvoke(iar); 
}, null);

那边大家使用委托的BeginInvoke方法来打开线程,实行异步调用。如上面代码所示,那里介绍了Action与Func的最基础的异步应用。

寄托,架构的血流

信托是架设的血液,假若系统中尚无嘱托,那代码将堆叠到联合,比大力胶粘的都密不可分。

就好比一碗汤面倒掉了富有的汤,只要它静放3个阵子,就会变成一坨面球,让你不能够下嘴。

故此,委托是架设的血流,是框架的流利的水源。

那么委托到底是何许流动的吧?

大家先从刚介绍过的委托的线程应用说起。


先是主导应用——随手线程:

笔者们在做开发的时候,一定接触过父类。父类是为什么的吗?父类经常是用来编排公共属性和函数,方便子类调用的。

那大家的嘱托的第五个为主应用,正是父类的公共函数,线程随手运行。怎么样随手翻开呢?

第叁,我们创造父类代码如下:

class BaseDelegateSyntax
{ 
    public void AsyncLoad(Action action)
    {

    }
    public void AsyncLoad(Action action, Action callback)
    {
        IAsyncResult result = action.BeginInvoke((iar) =>
        {
            callback();
        }, null);
    }
    public void AsyncLoad<T>(Action<T> action, T para, Action callback)
    {
        IAsyncResult result = action.BeginInvoke(para, (iar) =>
        {
            callback();
        }, null);
    }
    public void AsyncLoad<T, R>(Func<T, R> action, T para, Action<R> callback)
    {
        IAsyncResult result = action.BeginInvoke(para, (iar) =>
        {
            var res = action.EndInvoke(iar);
            callback(res);
        }, null);
    }
}

小编们看出上面的代码,父类中添加了八个异步委托的调用函数,接下去,大家就能够在后续该类的子类中,随手翻开线程了。

子类代码如下:

class ChildDelegateSyntax : BaseDelegateSyntax
{
    public void Excute()
    {
        //开启异步方法
        base.AsyncLoad(() => { });

        //开启异步方法,并且在异步结束后,触发回调方法
        base.AsyncLoad(() => { },
            ()=> 
            {
                //我是回调方法
            });

        //开启异步有入参的方法,传递参数,并且在异步结束后,触发回调方法
        base.AsyncLoad<string>((s) => { },"Kiba518",
           () =>
           {
                //我是回调方法
           });

        //开启异步有入参的方法,传递字符串参数Kiba518,之后返回int型结果518,
        //并且在异步结束后,触发回调方法,回调函数中可以获得结果518
        base.AsyncLoad<string,int>((s) => {
            return 518;
        }, "Kiba518",
           (result) =>
           {
               //我是回调方法 result是返回值518
           });
    }
}

看了上边的父子类后,是还是不是觉得委托让我们眼花缭乱的线程世界变简洁了吗?


第②骨干应用——穿越你的世界:

接下去,我们来看委托的第一种为主用法,穿越的利用。

其一应用,是最广大,也最家常的行使了。因为委托是援引类型,所以A类里定义的委托,能够在被内部存款和储蓄器回收在此以前,被别的类调用。

我们常常会在种种论坛看到有人提问,A页面如何调用B页面包车型地铁性质、方法、父页面获取子页面包车型客车习性、方法,也许子页面获取父页面包车型大巴性格、方法。

实际,只要定义好委托,并将委托正确的传递,就能够兑现穿越的调用了。

上面大家看下穿越应用的代码。

public class FirstDelegateSyntax
{
    public FirstDelegateSyntax()
    {
        Console.WriteLine(" First 开始 "  );
        SecondDelegateSyntax sds = new SecondDelegateSyntax(()=> {
            Console.WriteLine(" First传给Second委托被触发 ");
        });
        sds.Excute();
        Console.WriteLine(" First 结束 ");
    }
}

public class SecondDelegateSyntax
{
    public Action Action { get; set; }
    public SecondDelegateSyntax(Action _action)
    {
        Console.WriteLine(" Second的构造函数 ");
        Action = _action;
    }
    public void Excute()
    {
        Console.WriteLine(" Second的Excute被触发 ");
        Action();
    }
}

咱俩得以看到,大家传递的委托,穿越了本人所属的类。在SecondDelegateSyntax类中被触发了。

运作结果如下:

亚洲必赢官网 10

其三中坚应用——回调函数:

世界上本没有回调函数,叫的人多了,也就有了。

请牢记,全体的回调函数,都以委托的通过应用,全部的回调函数;都是信托的穿越应用;全部的回调函数,都以委托的通过应用。

关键的话要讲2次。

因为委托是援引类型,所以能够被[址传递]。函数是不可以被传送的。

当您传递函数的时候,其实是匿名传递了二个寄托的地方。

结语

寄托是大家最常用的语法,它将函数封装成引用类型的变量,供别的单位调用。

因为委托的特质是引用类型,所以决定了委托是能够展开址传递。也便是说,委托是连连于大家系统代码中的列车。

大家能够在火车上放很多居多东西,在急需的站点,叫停火车,并将托运的事物搬下来使用。

故此,理论上,只要大家运用好委托,就可以大大方方滑坡冗余的代码。

但委托这种列车,是各类程序员都得以定义的,假若多少个项目中有11个开发者,每种人都在概念委托,那么,就有或者出现定义了十二个一样的寄托的处境,那样就应运而生了撞车的光景。

为此委托在动用的时候,尽量做到有序传递,即预先做好列车的行驶路线,让委托遵照路径运维。尽量不要定义能够被此外单位调用的公共委托。

倘若要求公共委托,能够选择反射的措施来调用。

末端笔者会继续写事件,音信,反射等语法,敬请期待。

C#语法——元组类型

C#语法——泛型的三种应用

C#语法——await与async的正确性打开药方式


注:此文章为原创,欢迎转发,请在篇章页面鲜明地点给出此文链接!
若你认为那篇作品勉强能够,请点击下右下角的【推荐】,分外多谢!
比方您觉得那篇小说对您拥有帮助,那就不要紧支付宝小小打赏一下啊。 

亚洲必赢官网 11

 

网站地图xml地图