/* .Net 的 delegate 与 event 的实现是不可分的!属于基础知识!
有这样一道 .Net/C# 面试题:
请以事件的概念实现: 控制台屏幕录入任意字符串,并回显 "你键入了:" + 你刚才键入的字符串,如果键入 "q",退出程序,运行结束!
.Net 的 delegate 与 event 的实现是不可分的!属于基础知识!
写惯了 Windows 下的事件响应程序,真正从头到尾实现事件不常见! 我有两篇老文章:
《C# 写的 HttpRequsetResponse 类,异步、事件... 还热乎着呢!》 http://www.csdn.net/Develop/read_article.asp?id=19254 http://blog.csdn.net/playyuer/archive/2003/07/03/2856.aspx
《TreeView 的派生类: TreeViewEx 实现 NodeShowToolTip、NodeDoubleClick 事件》 http://www.csdn.net/Develop/Read_Article.asp?Id=19246 http://blog.csdn.net/playyuer/archive/2003/06/26/2857.aspx
也只是在 WinForm 下部分的实现了事件!
我的最简单的参考答案,都是用 static 方法实现的: */ /* class Class1 { public delegate void FireEventHandler(string s); public static event FireEventHandler FireStatic; static bool b = false; static void Main(string[] args) { FireStatic += new FireEventHandler(Fire1); System.Console.WriteLine("请键入任意字符(串),\"q\" 退出!"); string s; while (true) { s = System.Console.ReadLine(); FireStatic(s); if (b == true) break; } } static void Fire1(string s) { if (s != "q") { System.Console.WriteLine("你键入了: " + s); } else { System.Console.WriteLine("不送了!"); b = true; } } } */ /*
经常编写 WinForm 程序的人应该熟悉,我想应该还是有人不知道具体怎样实现的事件! 这些人实际并不一定真知道: this.button1.Click += new System.EventHandler(this.button1_Click) 的 EventHandler 到底是怎么实现的?不过这确实不妨碍编写 Click 事件的响应代码!
今天我也复习了一下,用 C# Console 程序跟大家分享一下: 请一定要注意程序注释,运行时注意屏幕提示:
*/ // 请存为任意 *.cs 文件后,csc 成 exe 文件! class Class1 { //声明一个委托 delegate FireEventHandler,delegate 没有 静态或实例 成员的说法 public delegate void FireEventHandler(string s);
//声明 FireEventHandler 委托类型的事件 //亦即将 FireEventHandler 理解为数据类型,易理解 public event FireEventHandler FireInstance; public static event FireEventHandler FireStatic;
static void Main(string[] args) { System.Console.WriteLine("Hello World");
//用 delegate: FireEventHandler() 委托,建立委托关系 //Static 方法 FireStatic() 代理(被委托)了 Static 方法 Fire1() FireStatic += new FireEventHandler(Fire1); //Static 方法 FireStatic() 代理(被委托)了 Instance 方法 .Fire2() FireStatic = FireStatic + new FireEventHandler(new Class1().Fire2);
Class1 c = new Class1(); //Instance 方法 .FireInstance() 代理(被委托)了 Instance 方法 .Fire2() c.FireInstance += new FireEventHandler(c.Fire2);
//Instance 方法 .FireInstance() 代理(被委托)了 Static 方法 Fire1() c.FireInstance = new FireEventHandler(Fire1) + c.FireInstance; //以上仅是声明了委托关系,尚未执行 委托代理方法 !
System.Console.WriteLine("下面列印委托关系:"); System.Console.WriteLine("Static 方法 FireStatic() 作为代理接受以下委托:"); ListDelegateRelation(FireStatic);
System.Console.WriteLine();
System.Console.WriteLine("Instance 方法 .FireInstance() 作为代理接受以下委托:"); ListDelegateRelation(c.FireInstance);
System.Console.WriteLine("请键入任意字符(串),\"q\" 退出!"); string s; while (true) { s = System.Console.ReadLine(); System.Console.WriteLine("--------------------------"); System.Console.WriteLine("以下是键入 \"{0}\" 后,触发事件的响应:"); //我们在此编程,即:在接受屏幕行录入后,令程序执行委托代理方法! //从而触发了事件! // FireStatic 静态事件被触发了 FireStatic("FireStatic 静态事件被触发了:\nStatic 方法 FireStatic() 受委托代理执行了 {0}\n你键入了: [" + s + "]\n");
// .FireInstance 实例事件被触发了 c.FireInstance(".FireInstance 实例事件被触发了: \nInstance 方法 .FireInstance() 受委托代理执行了 {0}\n你键入了: [" + s + "]\n"); System.Console.WriteLine("======================================="); System.Console.WriteLine("请键入任意字符(串),\"q\" 退出!"); if (s == "q") break; } ///* //解除委托关系可用 "-=" //下面解除委托,列印剩余委托关系 ListDelegateRelation(FireStatic);
FireStatic -= new FireEventHandler(Fire1); ListDelegateRelation(FireStatic);
FireStatic = FireStatic - new FireEventHandler(new Class1().Fire2); ListDelegateRelation(FireStatic);
c.FireInstance = new FireEventHandler(Fire1) - c.FireInstance; ListDelegateRelation(c.FireInstance);
c.FireInstance = c.FireInstance - new FireEventHandler(Fire1); ListDelegateRelation(c.FireInstance);
//*/ }
//静态方法 static void Fire1(string s) { //响应事件的程序 System.Console.WriteLine(s.Replace("{0}","static 方法 Fire1()")); }
//实例方法 void Fire2(string s) { //响应事件的程序 System.Console.WriteLine(s.Replace("{0}","Instance 方法 .Fire2()")); }
static void ListDelegateRelation(FireEventHandler x) { if (x != null) { // foreach (System.Delegate d in x.GetInvocationList()) foreach (FireEventHandler d in x.GetInvocationList()) { System.Console.WriteLine(x.ToString() + " 类型的事件代理了 " + (d.Method.IsStatic ? x.Target + " 类的 Static 方法 ":d.Target + " 的 Instance 方法 .") + d.Method.Name); } } else { System.Console.WriteLine("没有任何委托关系"); } } }
/* 下面是一个更复杂点的 Console 程序,根据 输入数字的奇偶性触发不同的事件! */ /* using System.Text.RegularExpressions; class Class1 { private static Class1 x; static void Main(string[] args) { System.Console.WriteLine("Hello World"); x = new Class1();
//设置委托 delegate 关系 //把 += 右边的 委托 给左边 的 (-= 是取消委托关系) //以后就可以用对"左边"的方法签名的调用,实际就是相当于调用了"右边"的方法的执行 //将 Class1 的实例方法(x.Fire1) 委托给 Class1 的实例事件(x.FireInstance) x.FireInstance += new Class1.FireEventHandler(x.Fire1);
//将 Class1 的静态方法(Class1.Fire2) 委托给 Class1 的实例事件(x.FireInstance) x.FireInstance += new Class1.FireEventHandler(Class1.Fire2);
//将 Class1 的静态方法(Class1.Fire2) 委托给 Class1 的静态事件(Class1.FireStatic) Class1.FireStatic += new Class1.FireEventHandler(Class1.Fire3);
//将 Class1 的实例方法(x.Fire1) 委托给 Class1 的静态事件(Class1.FireStatic) Class1.FireStatic += new Class1.FireEventHandler(x.Fire4);
int i; string s; while (true) { if ((s = System.Console.ReadLine()) == "q") { break; } if (Regex.IsMatch(s,@"^\d+$")) { i = System.Convert.ToInt32(s); if (i % 2 == 0) { //输入时偶数触发该事件 x.OnFireInstance();//调用实例方法触发事件 } else { //输入时基数触发该事件 Class1.OnFireStatic(); //调用静态方法触发事件 } } } } public string Fire1() //实例方法 { System.Console.WriteLine("输入是偶数"); return null; } public static string Fire2() //静态方法 { System.Console.WriteLine("输入是偶数"); return null; } public static string Fire3() //静态方法 { System.Console.WriteLine("输入是奇数"); return null; } public string Fire4() //实例方法 { System.Console.WriteLine("输入是奇数"); return null; }
//大多数委托是不需要返回值!
public delegate string FireEventHandler(); //实例事件 public event FireEventHandler FireInstance;
//静态事件 public static event FireEventHandler FireStatic;
//实例方法 public void OnFireInstance() { //实例方法触发实例事件 //根据委托关系的声明: //委托执行时: 将实际调用执行 Fire1 和 Fire2 this.FireInstance(); //实例方法触发实例事件 委托执行 System.Console.WriteLine("以下是错误答案: 仅是测试\"实例方法\"触发\"静态事件\""); //实例方法触发静态事件 //根据委托关系的声明: //委托执行时: 将实际调用执行 Fire3 和 Fire4 FireStatic(); //实例方法触发静态事件 委托执行 }
//静态方法 public static void OnFireStatic() { //静态方法触发静态事件 //根据委托关系的声明: //委托执行时: 将实际调用执行 Fire3 和 Fire4 FireStatic();
System.Console.WriteLine("以下是错误答案: 仅是测试\"静态方法\"触发\"实例事件\""); //实例成员 x 就是为这里调用实例事件方法! //静态方法触发实例事件 //根据委托关系的声明: //委托执行时: 将实际调用执行 Fire1 和 Fire2 x.FireInstance(); //静态方法触发实例事件 委托执行 } } */ 
|