复习一下 .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
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值