委托和事件

回调(call back)函数是windows编程的一个重要部分,回调函数实际上就是方法调用的指针,也称为函数指针,是一个非常强大的编程特性。在.NET中以委托的形式实现了函数指针的概念,委托是类型安全的。本文主要描述C#中委托和事件的原理和实现。

一、委托

1.1 在C#中使用委托

在C#中,最好将委托看作是对象的一种新类型。使用委托和类一样,需要先定义,然后实例化。定义委托的语法如下:
None.gif delegate   void  VoidPreration( uint  x);
这里定义了一个委托VoidPreration,并指定该委托的每个实例都包含一个方法的细节,该方法带有一个uint参数,并返回void。委托的类型安全性非常重要,定义委托时,必须给出它所代表的方法的全部细节。
委托的实例化语法如下:
None.gif public   void  SomeMethod( uint  x)
ExpandedBlockStart.gifContractedBlock.gif
dot.gif {
InBlock.gif  
//dot.gif.
ExpandedBlockEnd.gif
}

None.gif
static   void  Main()
ExpandedBlockStart.gifContractedBlock.gif
dot.gif {  
InBlock.gif  VoidPreration voidPreration 
= new VoidPreration(SomeMethod);//实例化委托
InBlock.gif
  voidPreration();//委托实例的调用
ExpandedBlockEnd.gif
}

注意:给定委托的实例时,可以表示任何类型的任何对象上的实例方法或静态方法——只要方法的特征匹配于委托的特征即可。

1.2 委托实例

下面给出两个使用委托的实例
None.gif // 在这个示例中,定义一个类MathsOperation,它有两个静态方法,对double类型的值执行两个操作,然后使用该委托调用这些方法。
None.gif
using  System;
None.gif
namespace  SimepleDelegate
ExpandedBlockStart.gifContractedBlock.gif
dot.gif {
InBlock.gif  
//类 MathsOperations 
InBlock.gif
  public class MathsOperations
ExpandedSubBlockStart.gifContractedSubBlock.gif  
dot.gif{
InBlock.gif    
public static double MultiplyByTwo(double value)
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif      
return value*2;
ExpandedSubBlockEnd.gif    }

InBlock.gif    
public static double Square(double value)
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif      
return value*value;
ExpandedSubBlockEnd.gif    }

ExpandedSubBlockEnd.gif  }

InBlock.gif
InBlock.gif  
//定义委托
InBlock.gif
  delegate double DoubleOp(double x);
InBlock.gif  
//测试
InBlock.gif
  public class MainEntryPoint
ExpandedSubBlockStart.gifContractedSubBlock.gif  
dot.gif{
InBlock.gif    
static void Main()
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif      DoubleOp[] operations 
= 
ExpandedSubBlockStart.gifContractedSubBlock.gif          
dot.gif{
InBlock.gif             
new DoubleOp(MathsOperations.MultiplyByTwo),
InBlock.gif             
new DoubleOp(MathsOperations.Square)
ExpandedSubBlockEnd.gif          }

InBlock.gif      
private void ProcessAndDisplayNumber(DoubleOp action, double value)
ExpandedSubBlockStart.gifContractedSubBlock.gif      
dot.gif{
InBlock.gif        
double result = action(value);
InBlock.gif        ConsoleWriteLine(
"value is {0}, result of operation is {1}",value,result);
ExpandedSubBlockEnd.gif      }

InBlock.gif      
for(int i = 0; i<operations.Length; i++)
ExpandedSubBlockStart.gifContractedSubBlock.gif      
dot.gif{
InBlock.gif        Console.WriteLine(
"using operation[{0}]:",i);
InBlock.gif        ProcessAndDisplayNumber(operation[i],
2.0);
InBlock.gif        Console.WriteLine();
ExpandedSubBlockEnd.gif      }

ExpandedSubBlockEnd.gif    }

ExpandedSubBlockEnd.gif  }

ExpandedBlockEnd.gif}

结果为:
None.gif using  operations[ 0 ]:
None.gifvalue 
is   2 ,result of operation  is   4
None.gif
None.gif
using  operation[ 1 ];
None.gifvalue 
is   2 ,result of operation  is   4

None.gif // BubbleSorter示例
None.gif
// 类BubbleSorter执行一个静态方法Sort(),这个方法的第一个参数时一个对象数组,把该数组按照升序重新排列。
None.gif
// 由于排序的数组可以是任意对象,所以这里需要定义一个委托
None.gif
delegate   bool  CompareOp( object  lhs,  object  rhs);
None.gif
// 类BubbleSorter
None.gif
public   class  BubbleSorter
ExpandedBlockStart.gifContractedBlock.gif
dot.gif {
InBlock.gif  
public static void Sort(object[] sortArray, CompareOp gtMethod)
ExpandedSubBlockStart.gifContractedSubBlock.gif  
dot.gif{
InBlock.gif    
for(int i = 0; i<sortArray.Length; i++)
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif      
for(int j = i+1; j<sortArray.Length;j++)
ExpandedSubBlockStart.gifContractedSubBlock.gif      
dot.gif{
InBlock.gif        
if(gtMethos(object[j],object[i]))
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif          
object temp = object[i];
InBlock.gif          
object[i] = object[j];
InBlock.gif          
object[j] = temp;
ExpandedSubBlockEnd.gif        }

ExpandedSubBlockEnd.gif      }

ExpandedSubBlockEnd.gif    }

ExpandedSubBlockEnd.gif  }

ExpandedBlockEnd.gif}

None.gif
None.gif
// 定义Employee类,建立要排序的数组
None.gif
public   class  Employee
ExpandedBlockStart.gifContractedBlock.gif
dot.gif {
InBlock.gif  
private string name;
InBlock.gif  
private decimal salary;
InBlock.gif  
public Employee(string name, decimal salary)
ExpandedSubBlockStart.gifContractedSubBlock.gif  
dot.gif{
InBlock.gif    
this.name =  name;
InBlock.gif    
this.salary = salary;
ExpandedSubBlockEnd.gif  }

InBlock.gif  
public override string ToString()
ExpandedSubBlockStart.gifContractedSubBlock.gif  
dot.gif{
InBlock.gif    
return string.Format(name + ", {0,C}",salary);
ExpandedSubBlockEnd.gif  }

InBlock.gif  
//比较大小的方法
InBlock.gif
  public static bool RhsIsGreater(object lhs, object rhs)
ExpandedSubBlockStart.gifContractedSubBlock.gif  
dot.gif{
InBlock.gif    Employee empLhs 
= (Employee)lhs;
InBlock.gif    Employee empRhs 
= (Employee)rhs;
InBlock.gif    
return (empRhs.salary >empLhs.salary)? true:false;
ExpandedSubBlockEnd.gif  }

ExpandedBlockEnd.gif}

None.gif
None.gif
// 测试
None.gif
public   class  MainEntryPoint
ExpandedBlockStart.gifContractedBlock.gif
dot.gif {
InBlock.gif  Employee[] employees 
= 
ExpandedSubBlockStart.gifContractedSubBlock.gif       
dot.gif{
InBlock.gif         
new Employee("wang",2000),
InBlock.gif         
new Employee("chen",1000),
InBlock.gif         
new Employee("zhu",3000),
InBlock.gif         
new Employee("li",2500)
ExpandedSubBlockEnd.gif       }
;
InBlock.gif  CompareOp employeeCompareOp 
= new CompareOp(Employee.RhsIsGreater);//实例化委托
InBlock.gif
  BubbleSorter.Sort(employees,employeeCompareOp);//委托调用
InBlock.gif
  for(int i = 0; i<employees.Length; i++)
ExpandedSubBlockStart.gifContractedSubBlock.gif  
dot.gif{
InBlock.gif    Console.WriteLine(employees[i].ToString());
ExpandedSubBlockEnd.gif  }

ExpandedBlockEnd.gif}

None.gif
None.gif
// 运行结果
None.gif

None.gifchen, $
1 , 000.00
None.gifwang, $
2 , 000.00
None.gifli, $
2 , 500.00
None.gifzhu, $
3 , 000.00

1.3 多播委托

前面介绍的委托都只包含一个方法调用,实际上委托可以包含多个方法,包含多个方法的委托叫做多播委托。如果调用多播委托,就可以按照顺序连续调用多个方法。为此多播委托的返回值必须是void(否则,返回值送到何处?)实际上,如果编译器发现某个委托返回void,就会自动假定这是一个多播委托。
None.gif delegate   void  DoubleOp( double  value);
None.gif
class  MainEntryPoint
ExpandedBlockStart.gifContractedBlock.gif
dot.gif {
InBlock.gif  
static void Main()
ExpandedSubBlockStart.gifContractedSubBlock.gif  
dot.gif{
InBlock.gif    DoubleOp operations 
= new DoubleOp(MathOperations.MultiplyByTwo);
InBlock.gif    operation 
+= new DoubleOp(MathOperations.Square);
InBlock.gif    dot.gifdot.gif
ExpandedSubBlockEnd.gif  }

ExpandedBlockEnd.gif}

None.gif
// 上面的多播委托等价于下面的代码
None.gif
DoubleOp operation1  =   new  DoubleOp(MathOperations.MultiplyByTwo);
None.gifDoubleOp operation2 
=   new  DoubleOp(MathOperations.Square);
None.gifDoubleOp operations 
=  operation1  +  operation2;
注意:如果使用多播委托,就应注意对同一个委托调用方法链的顺序并未正式定义,因此应避免编写依赖于任意特定顺序调用方法的代码。

二、事件

在开发基于对象的应用程序时,对象之间需要通信,例如在一个对象中发生了什么有趣的事情时,需要通知其它对象发生了什么变化,这里就需要用到事件。可以把事件作为对象之间通信的介质。而委托就用作应用程序接收到消息时封装事件的方式。
下面通过一个例子来说明C#中事件的创建、引发、接收和取消事件。

None.gif // 这个例子包含一个窗体,它会引发另一个类正在监听的事件。在引发事件后,接收对象就确定是否执行一个过程,如果该过程未能继续,就取消事件。
None.gif
// 用于生成事件的窗口包含一个按钮和一个标签
None.gif
namespace  EventTest
ExpandedBlockStart.gifContractedBlock.gif
dot.gif {
InBlock.gif    
public  partial class Form1 : Form
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif        
public delegate void ActionEventHandler(object sender, ActionCancelEventArgs ev);
InBlock.gif        
public static event ActionEventHandler Action;
InBlock.gif        
public BusEntity busEntity = new BusEntity();
InBlock.gif        
public Form1()
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            InitializeComponent();            
InBlock.gif            
ExpandedSubBlockEnd.gif        }

InBlock.gif
InBlock.gif        
private void OnAction(object sender, ActionCancelEventArgs ev)
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            
if (Action != null)
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                Action(sender, ev);
ExpandedSubBlockEnd.gif            }

ExpandedSubBlockEnd.gif        }

InBlock.gif
InBlock.gif        
private void button1_Click(object sender, EventArgs e)
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            ActionCancelEventArgs cancelEvent 
= new ActionCancelEventArgs();
InBlock.gif            OnAction(
this, cancelEvent);
InBlock.gif            
if (cancelEvent.Cancel)
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                
this.label1.Text = cancelEvent.Message;
ExpandedSubBlockEnd.gif            }

InBlock.gif            
else
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                
this.label1.Text = this.busEntity.TimeString;
ExpandedSubBlockEnd.gif            }

ExpandedSubBlockEnd.gif        }

InBlock.gif
ExpandedSubBlockEnd.gif    }

InBlock.gif    
public class ActionCancelEventArgs : System.ComponentModel.CancelEventArgs
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif        
string msg = "";
ExpandedSubBlockStart.gifContractedSubBlock.gif        
public ActionCancelEventArgs() :base()dot.gif{}
ExpandedSubBlockStart.gifContractedSubBlock.gif        
public ActionCancelEventArgs(bool cancel) : base(cancel) dot.gif{ }
InBlock.gif        
public ActionCancelEventArgs(bool cancel, string message)
InBlock.gif            : 
base(cancel)
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            
this.msg = message;
ExpandedSubBlockEnd.gif        }

InBlock.gif
InBlock.gif        
public string Message
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
ExpandedSubBlockStart.gifContractedSubBlock.gif            
get dot.gifreturn this.msg;}
ExpandedSubBlockStart.gifContractedSubBlock.gif            
set dot.gif{this.msg = value;}
ExpandedSubBlockEnd.gif        }

InBlock.gif        
ExpandedSubBlockEnd.gif    }

InBlock.gif
InBlock.gif    
//事件接收器
InBlock.gif
    public class BusEntity
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif        
string time = "";
InBlock.gif        
public BusEntity()
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            Form1.Action 
+= new Form1.ActionEventHandler(Form1_Action);
ExpandedSubBlockEnd.gif        }

InBlock.gif
InBlock.gif        
private void Form1_Action(object sender, ActionCancelEventArgs ev)
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            ev.Cancel 
= !DoAction();
InBlock.gif            
if (ev.Cancel)
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                ev.Message 
= "Wasn't the right time";
ExpandedSubBlockEnd.gif            }

ExpandedSubBlockEnd.gif        }

InBlock.gif        
private bool DoAction()
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            
bool retVal = false;
InBlock.gif            DateTime tm 
= DateTime.Now;
InBlock.gif            
if (tm.Second < 30)
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                
this.time = "The time is " + DateTime.Now.ToLongTimeString();
InBlock.gif                retVal 
= true;
ExpandedSubBlockEnd.gif            }

InBlock.gif            
else
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                
this.time = "";                
ExpandedSubBlockEnd.gif            }

InBlock.gif            
return retVal;
ExpandedSubBlockEnd.gif        }

InBlock.gif        
public string TimeString
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
ExpandedSubBlockStart.gifContractedSubBlock.gif            
get dot.gifreturn this.time; }
ExpandedSubBlockEnd.gif        }

ExpandedSubBlockEnd.gif    }

InBlock.gif
ExpandedBlockEnd.gif}

转载于:https://www.cnblogs.com/justnow/archive/2007/02/01/636951.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值