有这样一道 .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 方法实现的:
请以事件的概念实现: 控制台屏幕录入任意字符串,并回显 "你键入了:" + 你刚才键入的字符串,如果键入 "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 ;
}
}
}
{
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( " 没有任何委托关系 " );
}
}
}
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
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