41.事件(event)是类或对象用来“发出通知”的成员,通过提供事件的句柄,客户能够把事件和可执行代码联系在一起。
事件的声明中可以包含事件访问说明,或者依靠编译器自动提供一个访问器;它也可以省略事件访问说明,一次定义一个或多个事件。
注意:使用abstract修饰符的抽象事件必须省略事件访问说明,否则编译器会提示错误。
事件所声明的类型必须是一个代表(delegate)类型,代表类型应预先声明。
事件的预定是通过为事件加上+=操作符实现的,如 okButton.Click += new EventHandler(okButtonClick) (其中okButtonClick为单击事件的处理函数。)只要事件被触发,方法就会被调用。
事件的撤销则采用左操作符“-=”实现的。
对事件的触发相当于调用事件所表示的原型----delegate,所以对delegate型原型的调用必须先经过检查,确保delegate不是null型的。
如果每个事件的存储开销太大,就可以在类中包含事件访问声明,按私有成员的规则存放事件句柄列表。访问器的声明包括两种:添加访问器声明(add)和删除访问器声明(remove)。(在执行预定操作时使用添加型访问器,在执行撤销操作时使用删除型访问器。访问器中实际上还包含了一个名为value的隐藏的参数。不管是哪种事件访问器,都对应相应的一个方法,这个方法只有一个事件类型的值参数,摒弃返回值为void。)
System.EventHandler 实际被定义为一个代理
public delegate void EventHandler(
object sender, //事件源
EventArgs e
);
关于class EventArgs: 此类不包含事件数据,在事件引发时不向事件处理程序传递状态信息的事件会使用此类。如果事件处理程序需要状态信息,则应用程序必须从此类派生一个类来保存数据。
42.C#中索引指示器实际与C++中重载下标运算符”[]”类似;并用get和set定义对被索引的元素的读写权限。
如:class MyClass{
string[] names = new string[5];
public string this[int nIndex] {
get{
return names[nIndex];
}
set{
names[nIndex] = value;
}
}
}
43.C#中继承时在派生类前加上继承类型的关键字(public/private/protected),而在C++中继承时,此类关键字写在需要继承的基类之前,冒号之后。
44.C#中派生类继承基类后,若声明与基类成员同名的成员,编译器会警告,可使用new关键字关闭警告,但此时并不覆盖继承的成员。(如果使用new关键字,但是并没有重名的现象,则编译器会警告。不能载声明一个成员时同时使用new和override关键字。)
45.在C#中base作为关键字保留,用于派生类调用基类成员时简化书写。
46.C#中抽象类使用abstract修饰符,不能被实例化;而C++中抽象类是指包含纯虚函数(函数之后加有”=0”并且没有函数体)的类。
C#中抽象类不能同时又是密封的。
C#中抽象类作为基类,在派生类继承抽象类时,必须通过重载来实现所有继承而来的抽象成员,否则派生类也为抽象类。
抽象方法是用abstract修饰的方法,和C++中纯虚函数一样,他没有函数体。
抽象方法在派生类中不能使用base关键字来进行访问。
47.C#中如果想让一个类不能被继承,则可以使用sealed关键字修饰,密封类可以保证编写的类不被继承。(密封类由于不再有派生类,其中用virtual修饰的方法被转化为非虚的,virtual关键字在密封类中不再生效。)
用sealed修饰的方法称为密封方法,不能被继承。(不是类的每个成员方法都可以作为密封方法,密封方法必须对基类的虚方法进行重载,提供具体的实现方法。因此,sealed修饰符总是和override修饰符同时使用。)
48.从技术上来看,接口是一组包含了函数型方法的数据结构。
接口继承和类继承不同:
1).类继承不仅是说明继承,而且也是实现继承;而接口继承只是说明继承。派生类可以继承基类的方法实现,而派生的接口只继承了成员方法说明,而没有继承父接口的实现。
2).C#中类继承只允许单继承,但是在接口继承中允许多重继承。(逗号分隔多个父接口。Private或者internal类型的接口是不允许的,被继承的接口应该是可以访问的。)
接口可以包含一个或多个成员,成员可以使方法、数型、索引指示器和事件,但不能是常量、域、操作符、构造函数或析构函数,而且不能包含任何静态成员。
接口成员默认访问方式是public,接口成员在声明时不能包含任何修饰符,如abstract, public, protected, internal, private, virtual, override, static等修饰符。(但是可以使用new修饰符)接口成员中允许函数重载,继承而来的成员不用再声明,接口可以定义与继承而来的成员同名的成员来覆盖继承而来的成员。
当接口因为多重继承而产生成员重名的现象是,必须显示转化(指定)为相应的父接口(显示类型转换)来调用相应的成员。
类实现接口的声明方式类似继承:
class BaseClass{}
interface IMyClass {
void Fun();
void Fun(int arg);
void Fun2();
}
class MyClass : IMyClass{
void Fun(){…函数体…} //实现IMyClass中的Fun()方法
Void Fun(int arg){…函数体…}
……
}
//还允许在继承的同时加入接口的实现声明
如 public class MyClass2 : BaseClass, IMyClass //继承BaseClass并且实现IMyClass
{
……
}
注意:接口本身不提供所定义的成员的实现,它仅仅说明这些成员,这些成员必须依靠实现接口的类或其他接口的支持。(借腹生子)(实现接口的成员时不能加任何访问限制符。)
同一接口在不同类中的实现可以不同。
隐式实现接口成员时,需要在成员声明起始处加上访问修饰符(public, private,protected等),此修饰符与接口声明的访问修饰符相同。并且隐式声明的接口成员可以通过类或者接口的实例调用,而显示声明的不能通过类实例调用,只能通过接口实例调用(显示声明实现接口成员时不需要加访问修饰符)。
49.在C#中struct中成员和class成员默认的访问权限都是private;而在C++中struct的成员默认为public,而class中成员默认为private。