您的位置:首页 > 职场人生

黑马程序员_委托和事件

2013-11-21 16:16 218 查看

------- Windows Phone 7手机开发.Net培训、期待与您交流! ------- 

委托和事件

在C#开发中,有时需要实现这样的情况:只要新添加一个对象,就要执行一系列的方法。如果每次挨个调用,浪费时间,还使代码冗余。这时候可以使用委托。委托建立的是一个方法链条。设置好后,可以让一个对象依次去执行这个链条上的各个方法。它可以简化代码,提高代码效率,使代码容易维护。事件是一种特殊的委托,它在某些操作发生时自动地发出通知。

使用委托

委托是一个能够引用方法的对象,能够调用它所指向的方法。而且,在程序运行期间,同一个委托可以调用不同的方法,只要改变它引用的方法即可。所有委托类型的基类是System.Delegate类。System.Delegate类本身不是委托类型,而且不允许显式地直接从该类派生新的类型。

声明委托

委托同类一样,在使用之前需要声明。委托类型的声明
4000
将创建一个协定,该协定指定一个或多个方法的签名。委托是委托类型的实例,它可以引用静态方法或者实例方法。声明委托需要使用delegate关键字,委托的修饰符它包括new、public、protected、internal和private共5个关键字。其中,public、protected、internal和private修饰符控制委托的可访问性。

public修饰符:表示该委托是公开的,访问不受限制。

protected修饰符:表示该委托只能是本身委托访问。

internal修饰符:表示该委托只能是在当前应用程序中访问。

private修饰符:表示该委托只能是本身访问。

注意:只有在其他类型中声明委托时,才能够使用new修饰符。它表示所声明的委托会隐藏具有相同名称的继承成员。

声明名称为MyDelegate的委托MyDelegate委托的返回类型为int,方法参数为int i, int j。

public delegate int MyDelegate(int i,int j);     //声明委托MyDelegate

注意:委托类型默认是从System.Delegate派生的类类型,它隐含为密封类型,因此不能从委托类型派生一个新的类型。

向委托注册方法

委托声明好了后,就要给委托添加方法列表,使得创建对象后可以依次执行各个方法。给委托添加方法列表即创建向委托注册方法。如果一个方法要注册到某一个委托中,那么该方法的签名必须与该委托的所指定的签名完全匹配。

匹配规则:

方法的返回类型必须和委托的返回类型相同。

方法的方法参数必须和委托的方法参数相同,参数的具体名称可以不相同。

声明一个名称为MyDelegate的委托。MyDelegate委托的返回类型为int,方法参数为int i, int j。

public delegate int MyDelegate (int i,int j);   //声明委托MyDelegate

声明5个方法:F1、F2、F3、F4和F5,它们能否注册到MyDelegate委托的具体说明。

public void F1(int i,int j)方法:返回类型与MyDelegate委托不相同,不能注册到MyDelegate委托的方法列表中。

public void F2(int i)方法:返回类型与MyDelegate委托不相同,且方法参数也不相同,不能注册到MyDelegate委托的方法列表中。

public int F3(int i)方法:返回类型与MyDelegate委托相同,但是方法参数不相同,不能注册到MyDelegate委托的方法列表中。

public int F4(int i,int j)方法:返回类型与MyDelegate委托相同,且方法参数相同,能够注册到MyDelegate委托的方法列表中。

public int F5(int k,int l)方法:返回类型与MyDelegate委托相同,且方法参数相同(虽然参数的名称不相同),能够注册到MyDelegate委托的方法列表中。

public void F1(int i,int j){}            //不能注册到MyDelegate委托的方法列表中

public void F2(int i){}                   //不能注册到MyDelegate委托的方法列表中

public int F3(int i){}                    //不能注册到MyDelegate委托的方法列表中

public int F4(int i,int j){}             //能够注册到MyDelegate委托的方法列表中

public int F5(int k,int l){}             //能够注册到MyDelegate委托的方法列表中

实例化委托

委托也是一个类,因此,委托需要实例化。委托实例化可以创建委托类型的实例,并向该实例注册方法列表。委托类型的实例的方法列表可以为静态方法、实例方法或者另外一个委托实例。

注意:委托实例化,它把静态方法、实例方法或者另外一个委托的名称作为该实例的方法参数进行传递。

声明一个委托和一个类,它们的名称分别为MyDelegate和Program。MyDelegate委托的返回类型为int,方法参数为int i。

Program类声明两个方法:F1(int i)和F2(int j)。其中,F1(int i)方法为实例方法,F2(int j)方法为静态方法。然后Program类创建MyDelegate委托的两个个实例:d1和d2。

其中,d1实例将注册Program类的的实例p的实例方法F1(int i),d2实例将注册Program类的静态方法F2(int j)。

delegate int MyDelegate( int i );

class Program

{

   public int F1( int i )       // 声明一个实例方法

   {

      Console.WriteLine(" 调用实例方法 F1(int i) ");

      return i;

   }

   public static int F2(int j)   //声明静态方法

   {

      Console.WtiteLine(" 调用静态方法 F2( int j ) ");

      return j;

   }

   static void Main(string[] args)

   {

      Program p = new Program();

      MyDelegate d1 = new MyDelegate(p.F1);     //创建d1实例

      int i = d1(10);

      Console.WriteLine(" i = " + i );

      MyDelegate d2 = new MyDelegate(Program.F2);   //创建d2实例

      int j = d2(20);

      Console.WriteLine(" j = " + j);

      Console.ReadLine();

   }

}

构建委托的方法列表

使用委托可以将多个方法绑定到同一个委托变量。当调用此变量时,可以依次调用所有绑定的方法。每个委托实例都必须包含其方法列表,方法列表可以包含一个或多个方法。委托实例除了在其实例化时注册方法之外,还可以通过“+”或“+=”运算符向该实例的方法列表中注册方法,通过“-”或“-=”运算符从该实例的方法列表中移除方法。

声明一个委托和一个类,它们的名称分别为MyDelegate和Program。MyDelegate委托的返回类型为int,方法参数为int i。Program类声明两个静态方法:F1(int i)和F2(int i)。然后创建MyDelegate委托的5个实例:d1、d2、d3、d4和d5。它们的具体说明如下:

d1实例调用Program类的F1方法。

d2实例调用Program类的F2方法。

d3实例依次调用Program类的F1、F2方法。

d4实例依次调用Program类的F1、F2、F2、F1方法。

d5实例依次调用Program类的F1、F2、F1方法。

public delegate int MyDelegate ( int i );

public class Program

{

   public static int F1 ( int i )      // 定义静态方法 F1

   {

      Console.WriteLine(" 调用静态方法 F1 ( int i ) ");

      return i ;

   }

   public static int F2 ( int j )      // 定义静态方法 F2

   {

      Console.WriteLine(" 调用静态方法 F2 ( int j ) ");

      return j ;

   }

   static void Main(string[] args)

   {

      MyDelegate d1 = new MyDelegate( Program.F1 );           //注册方法 F1

      MyDelegate d2 = new MyDelegate( Program.F2 );           //注册方法 F2

      MyDelegate d3 = d1 + d2 ;           //给委托 d3 注册方法

      MyDelegate d4 = d3 + d2 + d1 ;           //给委托 d4 注册方法

      MyDelegate d5 = d4 + d2 ;           //给委托 d5 注册方法

      int i1 = d1( 20 );

      Console.WriteLine(" i1 =  " + i1 );

      int i2 = d2( 20 );

      Console.WriteLine(" i2 =  " + i2 );

      int i3 = d3( 20 );

      Console.WriteLine(" i3 =  " + i3 );

      int i4 = d4( 20 );

      Console.WriteLine(" i4 =  " + i4 );

      int i5 = d5( 20 );

      Console.WriteLine(" i5 =  " + i5 );

      Console.ReadLine();

   }

}

d1和d2实例通过“+”运算符得到d3实例。d1、d2和d3实例通过“+”运算符得到d4实例。d5实例等于d4实例-d2实例,即表示从d4实例的方法列表的末端开始查找。如果该方法被包括在d2实例的方法列表中,则从d4实例的方法列表中移除该方法。

调用委托

委托是一个方法链条,因此,调用委托实例就相当于调用了该委托实例包含的所有方法。如果一个调用列表包含多个方法时,当该委托实例被调用时,它将按照调用列表中方法的注册顺序依次调用每一个方法。

声明一个委托和一个类,它们的名称分别为MyDelegate和Program。MyDelegate委托的返回类型为void,方法参数为int i。

Program类声明两个静态方法:F1(int i)和F2(int i)。

F1(int i)方法输出“Program.F1:”和i参数的值,

F2(int i)方法输出“Program.F2:”和i参数的值。

Program类创建MyDelegate委托的5个实例:d1、d2、d3、d4和d5。

d1实例调用Program类的F1方法。

d2实例调用Program类的F2方法。

d3实例依次调用Program类的F1、F2方法。

d4实例依次调用Program类的F1、F2、F2、F1方法。

d5实例依次调用Program类的F1、F2、F1方法。

public delegate void MyDelegate ( int i );

public class Program

{

   public static void F1( int i )

   {

      Console.WriteLine(" Program.F1 " + i.ToString() );

   }

   public static void F2 ( int i )

   {

      Console.WriteLine(" Program.F2 " +i.ToString() );

   }

   static void Main(sting[]  args)

   {

      MyDelegate d1 = new MyDelegate(Program.F1);             // 创建 d1 实例调用 Program 类的 F1  方法

      MyDelegate d2 = new MyDelegate(Program.F2);             // 创建 d2 实例调用 Program 类的 F2  方法

      MyDelegate d3 = d1 + d2 ;              // d3 实例调用了 Program 类的 F1, F2 方法

      MyDelegate d4 = d3 + d2 + d1 ;              // d4 实例调用了 Program 类的 F1, F2 , F2 , F1方法

      MyDelegate d5 = d4 + d2 ;              // d5 实例调用了 Program 类的 F1, F2 , F1方法

      d1( 10 ) ;

      Console.WriteLine();

      d2( 200 );

      Console.WriteLine();

      d3( 3000 ) ;

      Console.WriteLine();

      d4( 40000 ) ;

      Console.WriteLine();

      d5( 500000 ) ;

      Cnsole.WriteLine(); 

      Console.ReadLine();

   }

}

d1(10);”表达式调用了d1实例,并调用了F1方法。

d2(200);”表达式调用了d2实例,并调用了F2方法。

d3(3000);”表达式调用了d3实例,并依次调用了F1、F2方法。

d4(40000);”表达式调用了d4实例,并依次调用了F1、F2、F2、F1方法。

d5(500000);”表达式调用了d5实例,并依次调用了F1、F2、F1方法。

使用事件

事件是某些操作发生时自动地发出通知,就像水开了之后发出声音,人听到声音就去关掉电源。事件构建在委托的基础上,它是一种信号机制。程序员可以通过提供事件处理程序为相应的事件添加可执行代码。当事件触发时,将调用该事件事先定义的方法。

声明事件

事件同委托一样,使用之前也需要声明。事件是一种特殊类型的委托,它包含两个参数:指示事件源的“对象源”参数和封装事件的其他任何相关信息的e参数。其中,e参数的类型为System.EventArgs类型或从System.EventArgs类派生的类型。

声明事件一般包括以下两个步骤。

(1)声明事件的委托

声明一个名称为EventHandler的事件委托,它包含两个参数:sender和e。其中,sender参数表示事件源,e参数表示与该事件相关的信息。

public delegate void EventHandler(object sender, EventArgs e);

(2)声明事件本身

在声明事件时,需要使用event关键字。

声明一个名称为Print的事件,它的类型为EventHandler。

public event EventHandler Print;   //声明事件Print

注册事件

事件同委托一样,需给事件注册方法列表。一个事件声明之后,该事件的默认值为null。

如果希望该事件执行事先指定的操作,则首先向该事件注册方法列表(即委托的调用列表)。注册事件可以使用“+=”运算符。

使用“+=”运算符向Print事件注册一个名称为F(object sender, EventArgs e)的方法。

public event void EventHandle ( object sender , EventArgs e );       // 定义委托

class Program

{

   public event EventHandle Print ;        // 定义事件

   public void F ( object sender , EventArgs e )

   {

      Console.WriteLine(" 调用方法 F( ) ");

   }

   static void Main(string[] args)

   {

      Program p = new Program();

      p.Print  +=  new EventHandle( p.F )      // 给事件 Print  注册方方法 F()

      if ( p.Print  !=  null )

      {

         p.Print ( null , null ) ;      // 调用事件

      }

      Console.ReadLine();

   }

}

移除事件

除了注册事件之外,还可以移除事件。移除事件使用“-=”运算符。

使用“-=”运算符从Print事件的方法列表中移除一个名称为F1 (object sender, EventArgs e)的方法。

 public delegate EventHandle ( object sender , EventArgs e );

 class Program

{

   public enevt EventHandle Print;

   public void F1 ( object sender , EventArgs e )

   {

      Console.WriteLine(" 方法 F1 ( ) ");

   }

   public void F2 ( object sender , EventArgs e )

   {

      Console.WriteLine(" 方法 F2 ( ) ");

   }

   static void Main(sting[] args)

   {

      Program p = new Program();

      p.Prin
a6b4
t  +=  new EventHandle ( p.F1 );             //添加方法

      p.Print  +=  new EventHandle ( p.F2 );

      Console.WriteLine(" 事件中的方法列表:  ");

      if ( p.Print  !=  null )

      {

         p.Print ( null , null );

      }

      Console.WriteLine();

      p.Print  -=  new EventHandle ( p.F1 );              // 移除方法

      Console.WriteLine(" 移除 F1 之后: ");

      if ( p.Print  !=  null )

      {

         p.Print ( null , null );

      }

      Console.ReadLine();

   }

}

调用事件

声明一个事件之后,如果没有向该事件注册方法,那么该事件的值为空(null)。因此,在调用事件时,往往需要检查该事件是否为空。

调用Print事件。在调用该事件之前,首先判断了该事件是否为空。只要当该事件不为空时,才调用该事件。调用Print事件的参数的值均为null。

public delegate void EventHandle ( object sender , EventArgs e );          // 创建一个委托 EventHandle

class Program

{

   public event EventHandle Print;                    //  定义事件 Print 

   public void F1( object sender , EventArgs e )       // 定义方法

   {

      Console.WriteLine(" 方法 F1 ");

   }

   static void Main(sting[] args)

   {

      Program p = new Program();               // 实例化类

      p.Print  +=  new EventHandle( p.F1 );      // 将 F1 方法添加到 Print 事件中去

      if ( p.Print  !=  null )

      {

         p.Print( null , null );         // 调用事件

      }

   Console.ReadLine();

   }

}

------- Windows Phone 7手机开发.Net培训、期待与您交流! ------- 

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: