代码改变世界

委托-异步调用-泛型委托-匿名方法-Lambda表达式-事件

2015-11-23 16:03  Lasthelloworld  阅读(450)  评论(0编辑  收藏  举报

1. 委托

From: http://www.cnblogs.com/daxnet/archive/2008/11/08/1687014.html

 

类是对象的抽象,而委托则可以看成是函数的抽象。一个委托代表了具有相同参数列表和返回值的所有函数。

[csharp] view plaincopy
 
  1. class Program  
  2. {  
  3.     delegate int CalculateDelegate(int a, int b);  
  4.   
  5.     int add(int a, int b)  
  6.     {  
  7.         return a + b;  
  8.     }  
  9.   
  10.     static void Main(string[] args)  
  11.     {  
  12.         CalculateDelegate d = new Program().add;  
  13.         //CalculateDelegate d = new CalculateDelegate(new Program().add);  
  14.         Console.WriteLine(d(1, 2));  
  15.         Console.ReadKey();  
  16.     }  
  17. }  


委托作为参数,在C#中非常常见。比如线程的创建,需要给一个ThreadStart或者ParameterizedThreadStart委托作为参数,而在线程执行的时候,将这个参数所指代的函数用作线程执行体。再比如:List<T>类型的Find方法的参数也是一个委托,它把“怎么去查找”或者说“怎么样才算找到”这个问题留给了开发人员。这有点像模板模式。

委托作为返回值一般会用在“根据不同情况决定使用不同的委托”这样的情形下。这有点像工厂模式。

 

2. 异步调用

From: http://www.cnblogs.com/daxnet/archive/2008/11/10/1687013.html

异步通过委托来完成。.net使用delegate来"自动"生成的异步调用是使用了另外的线程(而且是线程池线程)。

[csharp] view plaincopy
 
  1. class Program      
  2. {      
  3.     static TimeSpan Boil()      
  4.     {      
  5.         DateTime begin = DateTime.Now;      
  6.         Console.WriteLine("水壶:开始烧水...");      
  7.         Thread.Sleep(6000);      
  8.         Console.WriteLine("水壶:水已经烧开了!");      
  9.         return DateTime.Now - begin;      
  10.     }      
  11.     delegate TimeSpan BoilingDelegate();      
  12.      
  13.     static void Main(string[] args)      
  14.     {      
  15.         Console.WriteLine("小文:将水壶放在炉子上");      
  16.         BoilingDelegate d = new BoilingDelegate(Boil);      
  17.         IAsyncResult result = d.BeginInvoke(BoilingFinishedCallback, null);      
  18.         Console.WriteLine("小文:开始整理家务...");      
  19.         for (int i = 0; i < 20; i++)      
  20.         {      
  21.             Console.WriteLine("小文:整理第{0}项家务...", i + 1);      
  22.             Thread.Sleep(1000);      
  23.         }      
  24.     }      
  25.      
  26.     static void BoilingFinishedCallback(IAsyncResult result)      
  27.     {      
  28.         AsyncResult asyncResult = (AsyncResult)result;      
  29.         BoilingDelegate del = (BoilingDelegate)asyncResult.AsyncDelegate;      
  30.         Console.WriteLine("(烧水一共用去{0}时间)", del.EndInvoke(result));      
  31.         Console.WriteLine("小文:将热水灌到热水瓶");      
  32.         Console.WriteLine("小文:继续整理家务");      
  33.     }   
  34. }     


EndInvoke会使得调用线程阻塞,直到异步函数处理完成。EndInvoke会使得调用线程阻塞,直到异步函数处理完成。EndInvoke会使得调用线程阻塞,直到异步函数处理完成。EndInvoke会使得调用线程阻塞,直到异步函数处理完成。EndInvoke调用的返回值也就是异步处理函数的返回值。

 

3. 泛型委托

[Serializable]  

 

public delegate void EventHandler<TEventArgs>(object sender, TEventArgs e) where TEventArgs: EventArgs; 

 

 

[csharp] view plaincopy
 
  1. class IntEventArgs : System.EventArgs      
  2. {      
  3.     public int IntValue { get; set; }      
  4.     public IntEventArgs() { }      
  5.     public IntEventArgs(int value)       
  6.     { this.IntValue = value; }      
  7. }      
  8.      
  9. class StringEventArgs : System.EventArgs      
  10. {      
  11.     public string StringValue { get; set; }      
  12.     public StringEventArgs() { }      
  13.     public StringEventArgs(string value)       
  14.     { this.StringValue = value; }      
  15. }      
  16.      
  17. class Program      
  18. {      
  19.     static void PrintInt(object sender, IntEventArgs e)      
  20.     {      
  21.         Console.WriteLine(e.IntValue);      
  22.     }      
  23.      
  24.     static void PrintString(object sender, StringEventArgs e)      
  25.     {      
  26.         Console.WriteLine(e.StringValue);      
  27.     }      
  28.      
  29.     static void Main(string[] args)      
  30.     {      
  31.         EventHandler<IntEventArgs> ihandler =       
  32.             new EventHandler<IntEventArgs>(PrintInt);      
  33.         EventHandler<StringEventArgs> shandler =       
  34.             new EventHandler<StringEventArgs>(PrintString);      
  35.      
  36.         ihandler(null, new IntEventArgs(100));      
  37.         shandler(null, new StringEventArgs("Hello World"));      
  38.     }      
  39. }  


4. 匿名方法

http://www.cnblogs.com/daxnet/archive/2008/11/12/1687011.html

只需要给出方法的参数列表(甚至也可以不给)以及方法具体实现,而不需要关心方法的返回值,更不必给方法起名字。最关键的是,只在需要的地方定义匿名方法,保证了代码的简洁。比如用于委托作为函数参数。

[csharp] view plaincopy
 
  1. class Program      
  2. {      
  3.     static void Main(string[] args)      
  4.     {      
  5.         List<string> names = new List<string>();      
  6.         names.Add("Sunny Chen");      
  7.         names.Add("Kitty Wang");      
  8.         names.Add("Sunny Crystal");      
  9.      
  10.         List<string> found = names.FindAll(      
  11.             delegate(string name)      
  12.             {      
  13.                 return name.StartsWith("sunny",      
  14.                     StringComparison.OrdinalIgnoreCase);      
  15.             });      
  16.      
  17.         if (found != null)      
  18.         {      
  19.             foreach (string str in found)      
  20.                 Console.WriteLine(str);      
  21.         }      
  22.     }    
  23. }  


5. Lambda表达式

http://www.cnblogs.com/daxnet/archive/2008/11/14/1687010.html

从委托的角度来看,Lambda表达式与匿名方法没有区别。Lambda表达式的定义方式为:“([参数列表]) => 表达式”。

[csharp] view plaincopy
 
  1. class Program      
  2. {      
  3.     static void Main(string[] args)      
  4.     {      
  5.         List<string> names = new List<string>();      
  6.         names.Add("Sunny Chen");      
  7.         names.Add("Kitty Wang");      
  8.         names.Add("Sunny Crystal");      
  9.      
  10.         List<string> found = names.FindAll      
  11.             (      
  12.             // Lambda Expression Implementation      
  13.             name => name.StartsWith(      
  14.                 "sunny",       
  15.                 StringComparison.OrdinalIgnoreCase)      
  16.             );      
  17.      
  18.         if (found != null)      
  19.         {      
  20.             foreach (string str in found)      
  21.                 Console.WriteLine(str);      
  22.         }      
  23.     }      
  24. }   


 

6. 事件

http://www.cnblogs.com/daxnet/archive/2008/11/21/1687008.html

事件由委托定义。事件的触发方只需要确定好事件处理函数的签名即可。也就是说,触发方只需要定义在事件发生时需要传递的参数,而在订阅方,只需要根据这个签名定义一个处理函数,然后将该函数“绑定”到事件列表,就可以通过签名中的参数,对事件做相应的处理。