委托和事件

转载 2007年09月26日 11:02:00
委托和事件复习
2007-09-05 18:51

一、委托
委托实际上就是C
++里面的函数指针,你可以让这个指针指向委托定义时所声名的那种类型的函数。举个例子:

public delegate void 连接数据库委托();
表示:声名一个委托类型,这个委托叫“连接数据库委托”,它所能指向的函数都是返回值为void型,没有参数的函数。比如:
private void 连接Oracle数据库();
private void 连接SqlServer数据库();

我们现在的程序里面要根据用户设定的数据库类型,自动连接数据库。
程序里面可以这么写:
连接数据库委托 委托实例 
= null;

switch(目标数据库类型)
...{
case 数据库类型.Oracle数据库:
委托实例 
+= new 连接数据库委托(连接Oracle数据库);
break;
case 数据库类型.SqlServer数据库:
委托实例 
+= new 连接数据库委托(连接SqlServer数据库);
break;
}

委托实例(); 
//运行委托所指向的函数
这里就能根据上面的switch来执行相应的连接数据库函数了。

委托是种类型,所以跟其他类型一样,可以当参数传递。

委托还有一个重要特性就是多播(Multicasting)

就是说执行一个委托实例的时候,可以同时执行一个以上的函数。

比如说我的程序要连接Oracle数据库,同时还要连接SqlServer数据库,可以这么写:
委托实例 
+= new 连接数据库委托(连接Oracle数据库);
委托实例 
+= new 连接数据库委托(连接SqlServer数据库);

委托实例(); 
//运行委托所指向的函数
这样就同时执行了两个函数

二、委托例子的完整代码

//DelegateTest.cs
using System;
using System.Threading;

namespace ConsoleApp_CS
...{
       
public class AppClass
       
...{
           
public delegate void 连接数据库委托();

           
private static void 连接Oracle数据库()
           
...{
               Console.WriteLine(
"已经连接到Oracle数据库n");
           }


           
private static void 连接SqlServer数据库()
           
...{
               Console.WriteLine(
"已经连接到连接SqlServer数据库数据库n");
           }


           
public static void Main()
           
...{
               连接数据库委托 数据库连接;

               数据库连接 
= new 连接数据库委托(连接Oracle数据库);

               Console.WriteLine(
"<<仅连接到Oracle数据库");
               数据库连接();       
//仅连接到Oracle数据库

               数据库连接 
= new 连接数据库委托(连接SqlServer数据库);

               Console.WriteLine(
"<<仅连接到SqlServer数据库");
               数据库连接();       
//仅连接到SqlServer数据库

               数据库连接 
= null;

               数据库连接 
+= new 连接数据库委托(连接Oracle数据库);
               数据库连接 
+= new 连接数据库委托(连接SqlServer数据库);

               Console.WriteLine(
"<<同时连接到两个数据库");
               数据库连接();

               Console.Read();
           }

       }

}



三、事件
可以这么理解:当某件事发生的时候,会有一个广播信号,告诉大家什么事情发生了。某些人可能不关心股票事件,有些人不关心其他国家发洪水事件。这样事件就需要订阅,你只订阅你感兴趣的事件。当事件发生时,那些订阅该事件的订阅者就会收到一个信号,告诉你这个事件发生了。你可以对这个事件不闻不问,这个跟没订阅该事件一样,有些人会对这个事件进行一些处理,比如:
公司饮水机在我旁边,我关心饮水机是否没水了,所以我订阅一个“饮水机没水了”这个事件。
公司饮水机.饮水机没水了 
+= new 公司饮水机.饮水机没水了委托(我.换水);

这样,当饮水机没水了事件触发时,我就被通知要换水,执行的是“我”这个实例的“换水”方法。
饮水机Class 看起来大概是这样的:
public class 饮水机
...{
       
private int 水量 = 10;
       
public delegate void 饮水机没水了委托();
       
public event 饮水机没水了委托 饮水机没水了;

       
public void 出水(int 出水量)
       
...{
           Console.WriteLine(
"有人接水……");
           水量 
-= 出水量;
           Console.WriteLine(
"桶里还剩{0}升水", 水量);
           
if(水量 == 0)
           
...{
               当饮水机没水了();
           }

       }


       
public void 当饮水机没水了()
       
...{
           
if(饮水机没水了 != null)
           
...{
                Console.WriteLine(
"饮水机没水了,快来换水……");
                饮水机没水了();       
//触发这个事件
            }

       }

}


而公司员工Class 看起来大概是这样的:

public class 公司员工
...{
public void 换水()
...{
Console.WriteLine(
"我去换水,真累啊……");
}

}

Main函数里应该这样

饮水机 公司饮水机 
= new 饮水机();
公司员工 我 
= new 公司员工();

公司饮水机.饮水机没水了 
+= new 饮水机.饮水机没水了委托(我.换水);

for(int i=0; i<10; i++)
...{
公司饮水机.出水(
1);
Thread.Sleep(
1000);
}


Console.Read();
要注意的一点是:在“当饮水机没水了”函数内,应该判断“饮水机没水了”是否为null,否则就不要执行“饮水机没水了();”

四、事件例子的完整代码

//EventTest.cs
using System;
using System.Threading;

namespace ConsoleApp_CS
...{
      
public class 饮水机
      
...{
          
private int 水量 = 10;
          
public delegate void 饮水机没水了委托();
          
public event 饮水机没水了委托 饮水机没水了_事件;

          
public void 出水(int 出水量)
          
...{
              Console.WriteLine(
"有人接水……");
              水量 
-= 出水量;
              Console.WriteLine(
"桶里还剩{0}升水", 水量);
              
if(水量 == 0)
              
...{
                  当饮水机没水了();
              }

          }


          
public void 当饮水机没水了()
          
...{
              
if(饮水机没水了_事件 != null)
              
...{
                  Console.WriteLine(
"饮水机没水了,快来换水……");
                  饮水机没水了_事件();      
//触发这个事件
              }

          }

      }


      
public class 公司员工
      
...{
          
public void 换水()
          
...{
              Console.WriteLine(
"我去换水,真累啊……");
          }

      }


      
public class AppClass
      
...{
          
public static void Main()
          
...{
              饮水机 公司饮水机 
= new 饮水机();
              公司员工 我 
= new 公司员工();

              公司饮水机.饮水机没水了_事件 
+= new 饮水机.饮水机没水了委托(我.换水);

              
for(int i=0; i<10; i++)
              
...{
                  公司饮水机.出水(
1);
                  Thread.Sleep(
1000);
              }


              Console.Read();
          }

      }

}


------------------------------------------------------------

1.委派的实现过程。

首先来看一下委派,委派其实就是方法的传递,并不定义方法的实现。事件其实就是标准化了的委派,为了事件处理过程特制的、稍微专业化一点的组播委派(多点委派)。下面举一个例子,我觉得把委派的例子和事件的例子比较,会比较容易理解。

using System;
class Class1
...{

        
delegate int MathOp(int i1,int i2);

        
static void Main(string[] args)
        
...{

                MathOp op1
=new MathOp(Add);

                MathOp op2
=new MathOp(Multiply);

                Console.WriteLine(op1(
100,200));

               Console.WriteLine(op2(
100,200));

                Console.ReadLine();

        }


        
public static int Add(int i1,int i2)        ...{

                
return i1+i2;

        }


        
public static int Multiply(int i1,int i2)

        
...{

               
return i1*i2;

        }


}


首先代码定义了一个委托mathop,其签名匹配与两个函数add()和multiply()的签名(也就是其带的参数类型数量相同):

delegate int MathOp(int i1,int i2);

main()中代码首先使用新的委托类型声明一个变量,并且初始化委托变量.注意,声明时的参数只要使用委托传递的函数的函数名,而不加括号:

mathop op1
=new MathOp(Add);

(或为mathop op1
=new MathOp(Multiply);)

委托传递的函数的函数体:

public static int Add(int i1,int i2)

...{

        
return i1+i2;

}


public static int Multiply(int i1,int i2)

...{

       
return i1*i2;

}


然后把委托变量看作是一个函数名,将参数传递给函数。 Console.WriteLine(op1(
100,200));

console.writeline(op2(
100,200));

2.事件的实现过程

using System;

class Class1
...{

        
static void Main(string[] args)

        
...{

                Student s1
=new Student();

                Student s2
=new Student();

                s1.RegisterOK 
+=new Student.DelegateRegisterOkEvent(Student_RegisterOK);

                s2.RegisterOK 
+=new Student.DelegateRegisterOkEvent(Student_RegisterOK);

                s1.Register();

                s2.Register();

                Console.ReadLine();

        }


        
static void Student_RegisterOK()

        
...{

               Console.WriteLine(
"Hello");

        }


}


class Student
...{

        
public delegate void DelegateRegisterOkEvent();

        
public event DelegateRegisterOkEvent RegisterOK;

        
public string Name;

        
public void Register()

        
...{

                Console.WriteLine(
"Register Method");

               RegisterOK();

        }


}


在student类中,先声明了委托delegateregisterokevent(),然后使用event和要使用的委托类型(前面定义的delegateregisterokevent委托类型)声明事件registerok(可以看作是委托的一个实例。):

public delegate void DelegateRegisterOkEvent();

public event DelegateRegisterOkEvent RegisterOK;

然后在main()函数中,实例化student类,然后s1.registerok事件委托给了student_registerok 方法。通过“
+=”(加等于)操作符非常容易地为.Net对象中的一个事件添加一个甚至多个响应方法;还可以通过非常简单的“-=”(减等于)操作符取消这些响应方法。

然后,当调用s1.register()时,事件s1.registerok发生。
 

浅谈事件委托和this的用法

浅谈事件委托和this用法详解事件委托 事件委托是一种由其它元素而非事件目标元素来响应事件产生的行为的思想。比如用ul元素来处理其子元素li的事件。有多种方法来处理事件委托。标准方法来源于原生浏览器...
  • hengs_dream
  • hengs_dream
  • 2016年07月30日 22:29
  • 1015

C#中的委托和事件

C#中的委托和事件   前言   委托和事件在.NET框架中应用的很广泛,但是楼主因为知识尚浅,用到的不多,但是听前辈们说,这个委托和事件就像两座大山,只要翻过了这...
  • shanyongxu
  • shanyongxu
  • 2016年02月25日 17:09
  • 1105

[C#]委托和事件(详细讲解)

引言 委托 和 事件在 .Net Framework中的应用非常广泛,然而,较好地理解委托和事件对很多接触C#时间不长的人来说并不容易。它们就像是一道槛儿,过了这个槛的人,觉得真是太容易了,而没...
  • s10141303
  • s10141303
  • 2014年03月02日 00:23
  • 4149

Unity中对于委托、事件的应用

[引言] 这边文章主要是针对刚踏入这行的程序员,是我工作半年多来积累下来的一些经验,仅作为参考,也希望各位经验丰富的前辈多批评指正。 我是专科生毕业,我们学校所教的C#的内容其实只有非常非常基础的那些...
  • GhostOrange
  • GhostOrange
  • 2016年11月13日 18:01
  • 2132

委托和事件的区别

原文链接: 从使用层面上了解委托和事件的区别 从本篇文章中,我们将从代码层面知道委托和事件的差异和用处,并且我们不会用猫和老鼠之类奇怪的比喻来混淆大家。 首先,我们知道委托和事件都可以用来调用...
  • hjzyzr
  • hjzyzr
  • 2016年04月20日 17:10
  • 1560

js中的事件委托

起因: 1、这是前端面试的经典题型,要去找工作的小伙伴看看还是有帮助的; 2、其实我一直都没弄明白,写这个一是为了备忘,二是给其他的知其然不知其所以然的小伙伴们以参考; 概述: 那什么叫事件委...
  • u013035060
  • u013035060
  • 2017年03月07日 17:23
  • 975

事件委托技术原理和使用(js,jquery)

一:事件委托技术原理 摘自http://www.webhek.com/event-delegate/ 事件委托(event delegation),使用时间委托技术能让你避免对特定的每个节点添加事件监...
  • zsn851
  • zsn851
  • 2016年03月10日 11:18
  • 3034

jQuery的事件绑定与事件委托

在用jQuery的事件绑定时,会用到on()、bind()、live()、 delegate()这几个方法,但对他们的区别缺从未注意过,现稍总结一下,如有错误,欢迎指正。       参考文档: h...
  • aiolos1111
  • aiolos1111
  • 2016年07月28日 13:42
  • 5537

JavaScript 事件委托 以及jQuery对事件委托的支持

javascript 事件委托,javascript事件,jQuery事件委托
  • u010349169
  • u010349169
  • 2014年04月19日 13:15
  • 6430

java实现事件委托

事件委托 委托
  • shuciqi
  • shuciqi
  • 2014年05月13日 14:27
  • 2308
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:委托和事件
举报原因:
原因补充:

(最多只允许输入30个字)