1.什么是委托,为什么要使用委托

我正在埋头苦写程序,突然想喝水,但是又不想自己去掉杯水而打断自己的思路,于是我就想让女朋友去给我倒水。她去给我倒水,首先我得让她知道我想让她干什么,通知她之后我可以继续写自己的程序,而倒水的工作就交给了她。这样的过程就相当于一个委托。

在程序过程中,当程序正在处理某个事件的时候,我需要另外的程序代码去辅助处理一些事情,于是委托另一个程序模块去处理,而委托就可以达到这种目的,我可以利用委托通知另外的程序模块,该去调用哪个函数方法。委托其实就起到了这样一个作用,将函数签名传递到了另一个函数中。或许这样讲还是有些模糊,看看后面的具体实例。

2.委托的定义

delegate int Add(int num1,int num2);

delegate void ConvertNum(string result);

上面是定义两个委托的例子,其实很简单。声明一个委托使用delegate关键字,上面分别是定义的带返回值的委托和不带返回值的委托,

两个委托都有传递参数,当然也可以不传递参数。其实委托也是一个类,委托派生为System.MulticastDelegate,而System.MulticastDelegate

又继承System.Delegate,如果你知道这个也就明白委托其实是一个特殊的类。


 1 public delegate string TeaDelegate(string spText);
 2 
 3     public class DelegateSource
 4     {
 5         public void TestDelegate()
 6         {
 7             Operator op = new Operator();
 8             TeaDelegate tea = new TeaDelegate(op.GetTea);
 9             Console.WriteLine("去给我倒杯水");
10             Console.WriteLine();
11             string result=tea("去给我倒杯水");
12             Thread.Sleep(5000);
13             Console.WriteLine(result);
14             Console.WriteLine();
15         }
16     }
17 
18     public class Operator
19     {
20         /// <summary>
21         /// 确定是否还有水
22         /// </summary>
23         private bool flag = true;
24 
25         public string GetTea(string spText)
26         {
27             if (spText == "去给我倒杯水")
28             {
29                 if (flag)
30                 {
31                     return "老公,茶来了";
32                 }
33                 else
34                 {
35                     return "老公,没有水了";
36                 }
37             }
38             return "等待.......";
39         }
40     }  

输出结果

上面使用最普通的一种方式来定义了一个委托的使用,这个例子虽然很简单,但是能够很形象的描述委托的使用。

3.委托的三种形式

(1).推断


 1 public delegate string TeaDelegate(string spText);
 2 
 3     public class DelegateSource
 4     {
 5         public void TestDelegate()
 6         {
 7             Operator op = new Operator();
 8             TeaDelegate tea = op.GetTea;
 9             Console.WriteLine("去给我倒杯水");
10             Console.WriteLine();
11             string result=tea("去给我倒杯水");
12             Thread.Sleep(5000);
13             Console.WriteLine(result);
14             Console.WriteLine();
15         }
16     }
17 
18     public class Operator
19     {
20         /// <summary>
21         /// 确定是否还有水
22         /// </summary>
23         private bool flag = true;
24 
25         public string GetTea(string spText)
26         {
27             if (spText == "去给我倒杯水")
28             {
29                 if (flag)
30                 {
31                     return "老公,茶来了";
32                 }
33                 else
34                 {
35                     return "老公,没有水了";
36                 }
37             }
38             return "等待.......";
39         }
40     }

在委托定义的例子中我们看到委托的使用方法是在委托实例化的时候指定的[new DelegateName(FunctionName)],这里可能表述不是太但是代码应该看得白了。 而委托的推断,并没有new 委托这个步骤,而是直接将Function 指定给委托。

(2).匿名函数


 1 public delegate string TeaDelegate(string spText);
 2 
 3     public class DelegateSource
 4     {
 5         public void TestDelegate()
 6         {
 7             Operator op = new Operator();
 8             bool flag = true;
 9             TeaDelegate tea = delegate(string spText)
10             {
11                 if (spText == "去给我倒杯水")
12                 {
13                     if (flag)
14                     {
15                         return "老公,茶来了";
16                     }
17                     else
18                     {
19                         return "老公,没有水了";
20                     }
21                 }
22                 return "等待.......";
23             };
24 
25             Console.WriteLine("去给我倒杯水");
26             Console.WriteLine();
27             string result=tea("去给我倒杯水");
28             Thread.Sleep(5000);
29             Console.WriteLine(result);
30             Console.WriteLine();
31         }
32     }

至于匿名委托,给人的感觉更为直接了,都不用显示的指定方法名,因为根本没有方法,而是指定的匿名方法。匿名方法在.NET 中提高了

代码的可读性和优雅性。对于更多操作较少的方法直接写为匿名函数,这样会大大提高代码的可读性。这里有两个值得注意的地方: 第一,不能使用

跳转语句跳转到该匿名方法外,第二 不能使用ref,out修饰的参数

(3).多播委托


 1 public delegate string TeaDelegate(string spText);
 2 
 3     public class DelegateSource
 4     {
 5         public void TestDelegate()
 6         {
 7             Operator op = new Operator();
 8 
 9             TeaDelegate tea1 = op.GetTea;
10             TeaDelegate tea2 = op.Speak;
11             TeaDelegate tea = tea1 + tea2;
12 
13             Console.WriteLine("去给我倒杯水");
14             Console.WriteLine();
15             string result=tea("去给我倒杯水");
16             Thread.Sleep(5000);
17             Console.WriteLine(result);
18             Console.WriteLine();
19         }
20     }
21 
22     public class Operator
23     {
24         /// <summary>
25         /// 确定是否还有水
26         /// </summary>
27         private bool flag = true;
28 
29         public string GetTea(string spText)
30         {
31             if (spText == "去给我倒杯水")
32             {
33                 if (flag)
34                 {
35                     return "老公,茶来了";
36                 }
37                 else
38                 {
39                     return "老公,没有水了";
40                 }
41             }
42             return "等待.......";
43         }
44 
45 
46         public string Speak(string spText)47         {48             Console.WriteLine("\n去把我的设计图稿拿来");49             return null;50         }51     }

还是上面的那个实例,我不尽想让女朋友去给我掉杯水,还让她帮我将程序设计图稿拿过来。这个时候做的就不是一件事了,而是多件。

程序中也有很多这种情况,于是我们需要多播委托,在一个委托上指定多个执行方法,这是在程序中可以行的。上面提到了,委托直接继承于

System.MulticastDelegate,正是因为这个类可以实现多播委托。如果调用多播委托,就可以按顺序连续调用多个方法。为此,委托的签名就必须返回void;否则,就只能得到委托调用的最后一个方法的结果。所以在上面的这段代码中是得不到结果的

4.事件

使用C#编程,无论是WinForm,WebForm 给人很难忘得就是它的控件,而他们的控件库使用方式都是使用使用事件驱动模式,而事件驱动模式却少不了委托。话不多说,看代码能够更清好的理解事件和委托之间的联系.


 1 public delegate void MyDelegate(string name);
 2 
 3     public class EventSource
 4     {
 5         public event MyDelegate Event_Delegate;
 6 
 7         public void SetCustomer(string name)
 8         {
 9             Console.WriteLine("事件发生.....\n");
10             Console.WriteLine("hi! "+name);
11         }
12 
13         public void TestEvent()
14         {
15             EventSource source = new EventSource();
16             Console.WriteLine("订阅事件.....\n");
17             source.Event_Delegate += new MyDelegate(source.SetCustomer);
18             Console.WriteLine("触发事件.....\n");
19             source.Event_Delegate("hechen");
20             Console.WriteLine("..................");
21         }
22     }

上面的代码中我们定义了一个委托,然后定义了一个类EventSource,这个类中声明了一个事件。定义一个事件使用event 关键字,定义一

个event必须指定这个event传递消息的委托,在触发事件之前必需订阅事件,我们使用+= new 语法来订阅一个事件,也就相当于实例化一个事件。

当我们触发事件的时候,就会调用相应的方法去处理。

5. 泛型委托

委托是类型安全的引用,泛型委托就和我们常用的泛型类一样,这个类在使用的时候才能确定类型.通过泛型委托,我们可以在委托传递参数

之后知道它的类型.在.NET中有一个很典型的泛型委托:

public delegate voie EventHandler<TEventArgs>(object sender,TEventArgs e) where TEventArgs:EventArgs.

这是一个非常有特色的泛型委托,可能我们用的比较少,但是作用是不能忽视的。
我们看看三个非常具有代表性的泛型委托.现在.NET4.0已经出来了,但是泛型委托.NET2.0就出来了,Linq 大家用的那叫一个甜,

为啥 函数式编程风格,匿名方法,Lamda表达式表达式使用是如此的魅力。但是大家仔细观察过没有,Linq 中的方法有几个经常出现的参数:

Action<T>,Predicate<T>,Func<T, Result>

Func<T,
E>:封装一个具有一个参数并返回 E 参数指定的类型值的方法,T
是这个委托封装方法的参数类型,E是方法的返回值类型。当然Func<T, Result>
只是其中的一种情况,这个委托还有其他的几种情况:Func<T>
这个是方法没有参数,返回值类型是T;Func<T1,T2,Result>
这个方法有两个参数,类型分别为T1,T2,返回值是Result,还有Func<T1,T2,T3,Result>,Func<T1,T2,T3,T4,Result>
这几中情况,具体情况就不介绍了.我们还可以通过扩展类型,扩展为更多的参数.


 1 public void TestFunc()
 2         { 
 3             TEventSource eventSource=new TEventSource();
 4             Func<string, string> func = eventSource.GetTea;
 5             string result = func("茶");
 6             Console.WriteLine(result);
 7         }
 8 
 9         public string GetTea(string context)
10         {
11             if (context == "茶")
12             {
13                 return "茶来了";
14             }
15             else
16             {
17                 return "设计稿子来了";
18             }
19         }

Action<T>:封装一个方法,该方法只采用一个参数并且不返回值,包括Action<T>,Action<T1,T2>,Action<T1,T2,T3>,Action<T1,T2,T3,T4> 这几种情况,也可以通过扩展方法去扩展参数的个数 。


 1 public void TestAction()
 2         {
 3             TEventSource eventSource = new TEventSource();
 4             Action<string> action = eventSource.Speak;
 5             action("Action<T> 泛型委托");
 6         }
 7 
 8         public void Speak(string context)
 9         {
10             Console.WriteLine(context);
11         }

Predicate<T>:表示定义一组条件并确定指定对象是否符合这些条件的方法。该委托返回的是一个bool类型的值,如果比较满足条件

返回true,否则返回false.其实上面的Func 委托可以包含这个委托.不过这个委托和上面的两个不一样,它只有一种类型


 1 public void TestPredicate()
 2         {
 3             TEventSource eventSource = new TEventSource();
 4             Predicate<int> predicate = eventSource.IsRigth;
 5             Console.WriteLine(predicate(0));
 6         }
 7 
 8         public bool IsRigth(int value)
 9         {
10             if (value == 0)
11             {
12                 return true;
13             }
14             else
15             {
16                 return false;
17             }
18         }

6.异步委托

投票技术:

委托其实相当于一个线程,使用投票技术是使用异步委托的一种实现方式.Delegate类提供了方法BeginInvoke(),可以传送委托类型定义的输入参数,其返回类型为IAsyncResult。IAsyncResult的IsCompleted属性可以判断委托任务是否完成

异步委托投票技术

等待句柄:等待句柄是使用AsyncWaitHandle属性访问,返回一个WaitHandle类型的对象,它可以等待委托线程完成其任务。在这个参数中可以设置最大的等待时间。

异步委托等待句柄

异步回调:这个方式和投票技术有点类似,不过在投票方式中BeginInvoke()方法第三个参数指定了一个方法签名,而这个方法参数接收IAsyncResult 类型的参数。


 1 public delegate string AsyDelegate(string content);
 2 
 3     public class AsyncresultDelegate
 4     {
 5         public void TestAsync()
 6         {
 7             AsyDelegate del = GetTea;
 8             del.BeginInvoke("hechen", delegate(IAsyncResult ar) {
 9                 Thread.Sleep(5000);
10                 string result = del.EndInvoke(ar);
11                 Console.WriteLine(result);
12             }, null);
13             for (int i = 0; i < 100; i++)
14             {
15                 Console.WriteLine("等待.....");
16                 Thread.Sleep(1000);
17             }
18         }
19 
20         public static string GetTea(string content)
21         {
22             return "茶来了  " + content;
23         }
24     }
原帖地址:http://www.cnblogs.com/qingyuan/archive/2010/05/11/1732415.html

C# 委托知识总结【转】的更多相关文章

  1. net .异步委托知识

    以前在编程中,异步用的比较少,导致C# 一些基础的 东西用法都不怎么熟悉,经常要用的时候在去查找资料比较被动,而已没真正里面理解起来,始终感觉不是自己的知识 (题外话) 首先委托关键字  Delega ...

  2. C# 委托知识总结

    原文地址:http://www.cnblogs.com/qingyuan/archive/2010/05/11/1732415.html 1.什么是委托,为什么要使用委托 我正在埋头苦写程序,突然想喝 ...

  3. C#之委托和事件

    我想,读者们可能看过一部电影叫<全民目击>,在电影中,富豪林泰婚期将至,准新娘却惨死地下停车场,林泰的富二代女儿林萌萌成为最大嫌疑人,林泰不惜重金聘请国内顶级律师周莉为女儿辩护,而公诉方却 ...

  4. [.NET] C# 知识回顾 - 委托 delegate (续)

    C# 知识回顾 - 委托 delegate (续) [博主]反骨仔 [原文]http://www.cnblogs.com/liqingwen/p/6046171.html 序 上篇<C# 知识回 ...

  5. [C#] C# 知识回顾 - 委托 delegate

    C# 知识回顾 - 委托 delegate [博主]反骨仔 [原文]http://www.cnblogs.com/liqingwen/p/6031892.html 目录 What's 委托 委托的属性 ...

  6. [C# 基础知识系列]专题一:深入解析委托——C#中为什么要引入委托

    转自http://www.cnblogs.com/zhili/archive/2012/10/22/Delegate.html 引言: 对于一些刚接触C# 不久的朋友可能会对C#中一些基本特性理解的不 ...

  7. C#基础知识之事件和委托

    本文中,我将通过两个范例由浅入深地讲述什么是委托.为什么要使用委托.委托的调用方式.事件的由来..Net Framework中的委托和事件.委托和事件对Observer设计模式的意义,对它们的中间代码 ...

  8. C#基础知识六之委托(delegate、Action、Func、predicate)

    1. 什么是委托 官方解释 委托是定义方法签名的类型,当实例化委托时,您可以将其实例化与任何具有兼容签名的方法想关联,可以通过委托实例调用方法. 个人理解 委托通俗一点说就是把一件事情交给别人来帮助完 ...

  9. C#知识体系(二)用案例来理解委托与事件

    上一篇博客讲到了LinQ和lambda的常用方法 还有很多我们未知但c#设计团队已经为我们封装好的类和方法.随着我们不断的熟悉C#语言,渐渐的就会接触到其他的知识点,委托.事件.反射.线程.同步,异步 ...

随机推荐

  1. Ruby on Rails 中你使用了Kaminari 后,千万不要再引入will_pagination 这个Gem 了

    今日做开发的时候发现的这个问题 发现无论怎样配置都不能使用Kaminari 的Per 这个功能,分页大小也固定在了30 最开始还以为是Ransack 这个Gem 影响的,上网搜了很久发现没有 最后仔细 ...

  2. 【安全测试】sql注入

    SQL注入攻击是黑客对 数据库 进行攻击的常用手段之一,随着B/S模式应用开发的发展,使用这种模式编写应用程序的程序员越来越多,但是由于程序员水平及经验页参差不齐,相当大部分程序员在编写代码的时候没有 ...

  3. Access 2010入门、语文

    Access2010入门 数据管理库是按照数据结构来组织,存储和管理数据的仓库. 最早出现的数据库是网状DBMS 1970年,EFCodd博士提出关系模型的概念,提出关系模型的理论基础. SQL语言功 ...

  4. LayUI&前端问题汇总

    1.用JS获取地址栏参数的方法 采用正则表达式获取地址栏参数:( 强烈推荐,既实用又方便!) //通过data给form赋值,根据name赋给value $.fn.setForm = function ...

  5. Value cannot be null. Parameter name: source

    下图主要想说.net抛错后的优先级, 错误1是根本原因,排第一位: 错误2里的方法包含了错误1,排第二位: 错误3就是整个Action了. 类似这样的错误,按照这样的顺序来解决bug,相信很受用.

  6. 【转】大数据批处理框架 Spring Batch全面解析

    如今微服务架构讨论的如火如荼.但在企业架构里除了大量的OLTP交易外,还存在海量的批处理交易.在诸如银行的金融机构中,每天有3-4万笔的批处理作业需要处理.针对OLTP,业界有大量的开源框架.优秀的架 ...

  7. 从今天开始学习Swift--关于Swift (转)

    WWDC2014推出了新的编程语言,大家都站在了新的起跑线上,希望转发的本文能对园内的朋友一点介绍和帮助,如果大家对swift感兴趣,欢迎踊跃利用google. 原文地址:http://www.coc ...

  8. Python的历史与基本知识入门

    一.Python简介 1.1989年由"龟叔"Guido van Rossum在圣诞节期间打发无聊时间编写. 2.Python是一门弱类型解释性语言. 3.优点:代码简洁,明确,优 ...

  9. 20170802,css样式优先级

    样式的优先级 多重样式(Multiple Styles):如果外部样式.内部样式和内联样式同时应用于同一个元素,就是使多重样式的情况. 一般情况下,优先级如下: (外部样式)External styl ...

  10. dojo事件绑定

    Dojo如何动态绑定事件的小demo <html> <title>事件绑定测试test</title> <head></head> < ...