委托和事件

来源:互联网 发布:caffe python 教程 编辑:程序博客网 时间:2024/06/03 18:05

在c#中当要把方法传送给其他方法时,需要使用委托。

 

一,定义委托

定义委托就是告诉编译器这种类型的委托代表了哪种类型的方法,然后创建该委托的一个或多个实例。

delegate void VoidOperation(unit x);

该示例,定义了一个委托VoidOperation,并指定该委托的每个实例都包含一个方法的细节,该方法带有一个unit参数,并返回void,委托的类型安全性非常高,在定义委托时,必须给出它所代表的方法的全部细节。可以在定义类的任何地方定义委托。委托还可以添加上一般的访问修饰符。

定义委托之后就可以创建委托的一个实例,以存储特定方法的细节。

 

在创建委托的实例时,所创建的委托的实例仍称为委托。

 

二,使用委托

例如:

private delegate string GetString();

 

static void Main(string[] args)

{

  int x=40;

  double y=90;

  GetString first=new GetString(x.ToString);

  Console.WriteLine(first());

  first=new GetString(y.ToString);

  Console.WriteLine(first());

}

委托在语法上总是带有一个参数的构造函数,这个参数就是委托引用的方法,这个方法必须匹配最初定义委托时的签名。委托的一个特征是它们的类型是安全的,可以确保被调用的方法签名是正确的

委托的实例可以表示任何类型的任何对象上的实例方法或静态方法,只要方法的签名匹配于委托的签名即可。

 

三,匿名方法

通过匿名方法使用委托,匿名方法是用作委托参数的一个代码块。

例如:

delegate string Test(string val);

static void Main(string[] args)

{

  Test  anon=delegate(string param) 

  {

     param+=mid;

     param+="and this was added to the string.";

     return param;

  };

  Console.WriteLine(anon("Start of string"));

}

匿名方法的优点是减少了系统开销。

使用匿名方法时,必须遵循两个规则,在匿名方法中不能使用跳转语句跳到该匿名方法的外部,匿名方法外部的跳转语句不能跳到该匿名方法的内部。在匿名方法内部不能访问不安全的代码,另外也不能访问在匿名方法外部使用的ref和out参数,但可以使用在匿名方法外部定义的其他变量。

 

四,委托数组

delegate double DoubleOP(double x);

 

static void Main()

{

  DoubleOp[]  operation={new DoubleOp(Math.sin),new DoubleOp(Math.cos)};

  for(int i=0;i<operation.Length;i++)

  {

    Console.WriteLine(operation[i](8.9));

  }

}

 

五,多播委托

委托可以包含多个方法,这种委托称为多播委托,如果调用多播委托,就可以按顺序连续调用多个方法,为此,委托的签名就必须返回void,实际上,如果编译器发现某个委托返回void,就会自动假定这是一个多播委托。

例如:

delegate void DoubleOp(double value);

static void Main()

{

  DoubleOp operations=new DoubleOp(Math.sin);

  operations+=new DoubleOp(Math.cos);

}

这里使用+,+=为一个多播委托中添加两个操作,多播委托还识别运算符-,-=以从委托中删除方法调用。

 

六,事件

.net frameword把windows消息封装在事件中那样,也可以把事件用作对象之间的通信介质。

事件的委托在form的构造函数中写入代码。

委托就用作应用程序接收到消息时封装事件的方式。

现在,在事件接收器的某个地方有一个方法,它负责处理事件,在每次发生已注册的事件时,就执行这个事件处理程序,此时就要使用委托了,由于发送器对接收器一无所知,所以无法设置两者之间的引用类型,而是使用委托作为中介,发送器定义接收器要使用的委托,接收器将事件处理程序注册到事件中,连接事件处理程序的过程称为封装事件。

例如:一个名为btnOne的按钮

btnOne.Click+=new EventHandler(Button_Click);

这里告诉运行库,在引用btnOne的Click事件时,应执行Button_Click方法,EventHandler是事件用于把处理程序(Button_Click)赋予事件(Click)的委托,注意使用+=运算符把这个新方法添加到委托列表中,这类似于多播委托,可以为事件添加多个事件处理程序,由于这是一个多播委托,所以要遵循添加多个方法的所有规则,但是不能保证调用方法的顺序。

其中Button_Click方法的定义:

Private void Button_Click(object sender,Eventargs e){}

只要使用EventHandler委托,参数就应是object,表示引发事件的对象,把一个引用发送给引发事件的对象,就可以把同一个的事件处理程序赋予多个对象;参数EventArgs,表示包含有关事件的其他有用信息的对象,这个参数可以是任意类型,只要派生于EventArgs即可。

如果使用匿名方法,就不用Button_Click方法和btnTwo_Ckick方法了,事件代码如下:

btnOne.Click+=new EventHandler(lblInfo.Text="Button One was pressed");

btnTwo.Click+=new EventHandler(lblInfo.Text="Button Two was pressed");

btnTwo.Click+=new EventHandler(MessageBox.Show("This only happens in Button 2 click event"));

这两句代码,单击btnOne会改变标签上的文本,单击btnTwo不仅会改变文本,还会消失消息框。

原创粉丝点击