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

1. 委托

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

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

  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. }  
    class Program
    {
        delegate int CalculateDelegate(int a, int b);

        int add(int a, int b)
        {
            return a + b;
        }

        static void Main(string[] args)
        {
            CalculateDelegate d = new Program().add;
            //CalculateDelegate d = new CalculateDelegate(new Program().add);
            Console.WriteLine(d(1, 2));
            Console.ReadKey();
        }
    }


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

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

2. 异步调用

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

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

  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. }     
class Program    
{    
    static TimeSpan Boil()    
    {    
        DateTime begin = DateTime.Now;    
        Console.WriteLine("水壶:开始烧水...");    
        Thread.Sleep(6000);    
        Console.WriteLine("水壶:水已经烧开了!");    
        return DateTime.Now - begin;    
    }    
    delegate TimeSpan BoilingDelegate();    
   
    static void Main(string[] args)    
    {    
        Console.WriteLine("小文:将水壶放在炉子上");    
        BoilingDelegate d = new BoilingDelegate(Boil);    
        IAsyncResult result = d.BeginInvoke(BoilingFinishedCallback, null);    
        Console.WriteLine("小文:开始整理家务...");    
        for (int i = 0; i < 20; i++)    
        {    
            Console.WriteLine("小文:整理第{0}项家务...", i + 1);    
            Thread.Sleep(1000);    
        }    
    }    
   
    static void BoilingFinishedCallback(IAsyncResult result)    
    {    
        AsyncResult asyncResult = (AsyncResult)result;    
        BoilingDelegate del = (BoilingDelegate)asyncResult.AsyncDelegate;    
        Console.WriteLine("(烧水一共用去{0}时间)", del.EndInvoke(result));    
        Console.WriteLine("小文:将热水灌到热水瓶");    
        Console.WriteLine("小文:继续整理家务");    
    } 
}   


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

3. 泛型委托

[Serializable]  

publicdelegatevoid EventHandler<TEventArgs>(object sender, TEventArgs e) where TEventArgs: EventArgs; 

  1. class IntEventArgs : System.EventArgs      
  2. {      
  3.     public int IntValue { getset; }      
  4.     public IntEventArgs() { }      
  5.     public IntEventArgs(int value)       
  6.     { this.IntValue = value; }      
  7. }      
  8.      
  9. class StringEventArgs : System.EventArgs      
  10. {      
  11.     public string StringValue { getset; }      
  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(nullnew IntEventArgs(100));      
  37.         shandler(nullnew StringEventArgs("Hello World"));      
  38.     }      
  39. }  
class IntEventArgs : System.EventArgs    
{    
    public int IntValue { get; set; }    
    public IntEventArgs() { }    
    public IntEventArgs(int value)     
    { this.IntValue = value; }    
}    
   
class StringEventArgs : System.EventArgs    
{    
    public string StringValue { get; set; }    
    public StringEventArgs() { }    
    public StringEventArgs(string value)     
    { this.StringValue = value; }    
}    
   
class Program    
{    
    static void PrintInt(object sender, IntEventArgs e)    
    {    
        Console.WriteLine(e.IntValue);    
    }    
   
    static void PrintString(object sender, StringEventArgs e)    
    {    
        Console.WriteLine(e.StringValue);    
    }    
   
    static void Main(string[] args)    
    {    
        EventHandler<IntEventArgs> ihandler =     
            new EventHandler<IntEventArgs>(PrintInt);    
        EventHandler<StringEventArgs> shandler =     
            new EventHandler<StringEventArgs>(PrintString);    
   
        ihandler(null, new IntEventArgs(100));    
        shandler(null, new StringEventArgs("Hello World"));    
    }    
}


4. 匿名方法

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

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

  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. }  
class Program    
{    
    static void Main(string[] args)    
    {    
        List<string> names = new List<string>();    
        names.Add("Sunny Chen");    
        names.Add("Kitty Wang");    
        names.Add("Sunny Crystal");    
   
        List<string> found = names.FindAll(    
            delegate(string name)    
            {    
                return name.StartsWith("sunny",    
                    StringComparison.OrdinalIgnoreCase);    
            });    
   
        if (found != null)    
        {    
            foreach (string str in found)    
                Console.WriteLine(str);    
        }    
    }  
}


5. Lambda表达式

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

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

  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. }   
class Program    
{    
    static void Main(string[] args)    
    {    
        List<string> names = new List<string>();    
        names.Add("Sunny Chen");    
        names.Add("Kitty Wang");    
        names.Add("Sunny Crystal");    
   
        List<string> found = names.FindAll    
            (    
            // Lambda Expression Implementation    
            name => name.StartsWith(    
                "sunny",     
                StringComparison.OrdinalIgnoreCase)    
            );    
   
        if (found != null)    
        {    
            foreach (string str in found)    
                Console.WriteLine(str);    
        }    
    }    
} 


 

6. 事件

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

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

原文地址:https://www.cnblogs.com/zhouyunbaosujina/p/3209988.html