深入解析C#编程的事件
事件声明可以是事件域声明,也可以是事件属性声明。在每种情况下,声明都可以由属性集合、一个新修饰符、四个访问修饰符和静态修饰符的有效组合组成。
事件声明的类型必须是具有代表性的类型,并且代表类型必须至少与事件本身一样可访问。
一个事件域声明对应一个域声明宣布一个或多个具有代表性的类型域。只读修饰不在事件域声明允许。
一个事件属性声明对应一个属性声明,声明有代表性的一种属性。除了包含get访问器和set访问器的事件属性声明,成员名称和访问的声明是相同的那些属性声明和虚拟,重写抽象修饰符不允许。
在包含事件成员声明的程序文本中,事件成员与表示该类型的私有域或属性相关,该成员可以在允许使用域或属性的任何上下文中使用。
如果一个类或结构程序文本的外部包含事件成员声明,则此事件的成员只能作为+和- =操作符(右手操作,使用数量。这些操作符用于添加或删除事件成员的事件处理程序。此事件成员的访问操作符控制执行该操作的上下文。
+和- =仅在操作外事件的类型声明事件成员中使用,外部代码可以添加或删除事件句柄,但不能以任何其他方式获得数值或修改基本事件域或事件属性。
在示例
中的委托EventHandler(object sender,事件E);
公共类按钮:控件
{
公共事件EventHandler Click;
protected void OnClick(事件E){
如果(点击)!=单击)(这个,E);
}
公共空重置(){
单击= null;
}
}
这是在按钮类的单击事件域的使用没有限制。作为演示的一个例子,这个领域可以进行测试,修改,和用于代表打电话表达。班里的按钮OnClick方法的原因的单击事件的概念和呼叫,导致事件完全一样的事件成员代表因此造成事件没有特殊的语言结构,注意代表的呼叫是通过检查,代表不空了。
外部类按钮,单击的成员只能在+和-运算符右中使用,如下所示
点击新= EventHandler(…);
它在事件的调用列表中添加一个代表,单击
点击=新EventHandler(…);
它从单击事件的调用列表中移除一个代表。
在x或x = y = y操作的形式中,当x是引用x中发生的事件的成员时,外部包含声明的类型,操作的结果是无效的(与x数值相反)。
下面的示例演示如何将事件句柄连接到上面的类按钮实例中:
公共课logindialog:形式
{
Button OkButton;
Button CancelButton;
公共logindialog(){
按OK键=新按钮(…);
OkButton。点击=新EventHandler(OkButtonClick);
点击=新按钮(…);
点击。点击=新EventHandler(cancelbuttonclick);
}
Void OkButtonClick(object sender,事件E){
OkButton。单击事件 / /处理
}
无效cancelbuttonclick(object sender,事件E){
点击。点击事件 / /处理
}
}
在这里,logindialog构造函数创建两个按钮实例添加事件处理的点击事件。
事件成员是一个典型的域,如上面按钮示例所示。在每个事件中消耗一个字段存储是不可接受的。一个类可以定义事件的属性而不是事件域,并利用民营机制来存储基本的代表。(设想在某些情况下,大多数的事件处理,每个事件都是不可接受的使用领域,使用属性,而不是域允许开发者获得空间和时间上的。妥协的能力)
在示例
类控件:组件
{
事件的键/唯一
静态只读对象mousedowneventkey =新的对象();
静态只读对象mouseupeventkey =新的对象();
事件处理程序与密钥返回
保护委托geteventhandler(对象关键){…}
事件处理程序,该键与
protected void SetEventHandler(对象的关键,委托处理){…}
事件属性 / /鼠标
公共事件MouseEventHandler MouseDown {
得到{
Return (MouseEventHandler) GetEventHandler (mouseDownEventKey);
}
集合{
SetEventHandler(mousedowneventkey,值);
}
}
事件属性 / / MouseUp
公共事件MouseEventHandler MouseUp {
得到{
返回(mouseeventhandler)geteventhandler(mouseupeventkey);
}
集合{
SetEventHandler(mouseupeventkey,值);
}
}
}
课堂控制提供了一个事件的内部存储机制。方法是一个关键seteventhandler代表值有关,和方法geteventhandler返回与密钥相关的当前的代表。基本存储机制的设计是按照与空的代表类型关联的键没有消费,所以未处理的事件不占存储空间。
实例变量初始化函数
当一个构造函数不初始化一个形式的基函数或构造函数初始化(…),构造函数的实例字段在类中声明指定的初始化函数隐式执行。这是对任务序列相关,这在之前的直接基类构造函数隐式调用的构造函数入口直接执行。变量的初始化函数,它们出现在类声明的字面顺序执行。
构造函数的执行
实例变量初始化函数和构造函数初始化函数可以被视为自动插入构造函数主体的第一个句子。
使用系统集合;
班上的一个
{
int=1,y=1,计数;
公开a(){
计数= 0;
}
公共A(int n){
计数= n;
}
}
乙类:A
{
双SQRT2 =数学。Sqrt(2);
ArrayList项目=新的列表(100);
Int max;
公共b():这个(100){
项目。添加(默认);
}
公共b(int n):基(n - 1){
max = n;
}
}
多变量的初始化功能包括、和各种形式的构造函数初始化函数(基本)也包括在内。这个例子是下面的例子,其中每个注释指示自动插入语句(用于自动插入构造函数调用语法至少证明机制无效,)。
使用系统集合;
班上的一个
{
int,y,计数;
公开a(){
x=1;变量初始化器
y=1;变量初始化器
对象(调用);对象(构造函数)
计数= 0;
}
公共A(int n){
x=1;变量初始化器
y=1;变量初始化器
对象(调用);对象(构造函数)
计数= n;
}
}
乙类:A
{
双SQRT2;
列表项;
Int max;
公共b():这个(100){
b(100);调用b(int)构造函数
项目。添加(默认);
}
公共b(int n):基(n - 1){
SQRT2 =数学。Sqrt(2); / /变量的初始化
项目=新的数组(100); / /变量的初始化
A(n - 1);调用一个(int)构造函数
max = n;
}
}
注释变量初始化函数被转换为赋值语句,赋值语句在基类构造函数调用之前执行。这个顺序确保所有实例域在执行任何语句之前都由它们的变量初始化函数初始化:
班上的一个
{
公开a(){
printfields();
}
公共虚拟无效(printfields){ }
}
乙类:A
{
int=1;
y;
公共b(){
y=1;
}
printfields(){ public override void
console.writeline(X = { 0 },Y = { 1 }
}
}
当使用新的b()创建B的实例时,生成以下输出:
x=1,y=0
因为在调用基类构造函数之前执行变量初始化函数,所以x的值是1,但是y的值是0(int的默认值),这是由于y的赋值,直到基类构造函数返回为止。
默认构造函数
如果一个类不包含任何构造函数声明,就会自动提供一个默认构造函数。
公共(c):基(){ }
这里C是类的名称。默认构造函数完全调用直接基类的非参数构造函数。如果在直接基类中没有对非参数构造函数的访问,就会出现错误。
班级留言
{
对象发送;
字符串文本;
}
因为类不包含构造函数声明,所以它提供了一个默认构造函数。
班级留言
{
对象发送;
字符串文本;
公用(消息):基(){ }
}
私有构造函数
当一个类只声明一个私有构造函数时,其他类不能从这个类派生或创建一个类的实例:
触发类
{
私人触发(防止){} / /实例化
公共常量双PI = 3.14159265358979323846;
公共静态双罪(双x){…}
公共静态双COS(双x){…}
公共静态双Tan(双x){…}
}
触发类提供的方法和一组相关的常数,但不能被实例化。因此,它是一个单独的私有构造函数。注意,至少一个私有构造函数必须声明避免默认构造函数自动生成(通常具有公共可访问性)。
可选参数的构造函数
构造函数的这个(…)形式通常与可选构造函数参数的实现相关联。
类文本
{
公共(文本):这个(0, 0,空){ }
公共文本(int x,int y):这个(x,y,NULL){ }
公共文本(int x,int y,字符串s){
构造函数实现
}
}
前两个构造函数只为丢失的参数提供默认值。两个构造函数使用这个(…)构造函数初始化函数调用第三个构造函数,这些构造函数实际上初始化新实例:
文本t1 =新(文本);与文本相同(0, 0,null)
文本=新文本(5, 10);与文本相同(5, 10,null)
文本=新文本(5, 20,hello);
析构函数
析构函数是实现破坏类的实例的行为的一个成员:
对于声明析构函数的类,必须为析构函数声明指定一个标识符,如果指定了任何其他名称,就会发生错误。
析构函数声明的主体指定为了初始化类的一个新实例而执行的语句。这与具有返回类型的实例方法的主体有关。
实例
类测试
{
静态空主(){
A. F();
B. F();
}
}
班上的一个
{
静态a(){
console.writeline(,);
}
公共静态空f(){
console.writeline(A.f );
}
}
B类
{
静态B(){
console.writeline(初始化B);
}
公共静态空f(){
console.writeline(诚挚的);
}
}
将产生或以下输出:
初始化一个
A. F
初始化B
B. F
或以下输出:
初始化B
初始化一个
A. F
B. F