一、类型成员及访问限定
1. 类成员
一个类型可以包含零个或者多个一下成员:
常数:一个恒定不变的数值符号,增强程序可读性与可维护性,静态的。
字段:可读可写,也可以是自读,建议设置为私有,防止类型外的代码破坏。
实例构造器:特殊方法,用来将新对象实例字段初始化到正常的初始化状态。
类型构造器:特殊字段,用来将新对象静态字段初始化
其他略
2.访问限定修饰符与预定义特性
C# 默认是 Internal;
类型预定义特性:abstract(不被实例化),sealed(不被继承);
字段预定义特性:static(字段是类型状态),readonly(字段仅在构造器中被赋值);
方法预定义特性:static(类型状态,对对象状态一无所知)
virtual(继承链最末端方法被调用 )
new(不重写基类中的虚方法,仅仅是将其隐藏起来,仅应用与虚方法)
override(显式表明方法在重写基类虚方法)
abstract(表示派生类比较提供和该抽象方法签名一样的实现)
sealed(派生方法不能重写该方法,仅应用与虚方法)
二、常数与字段
1. 常数
必须是基元类型,编译时确定他的值,存放在托管模块的元数据中,是类型而非实例的一部分。不占用任何内存分配(直接嵌入到IL代码中);
常数隐形是static,所以C#不允许给常数家静态关键字
public const int a =23;
2. 字段
类型字段,系统在该类型被加载到应用程序域是为其分配内存地址,通常发生在该类型的方法第一次被JIT编译时;
实例字段,系统在该类型实例被构建时为其分配内存地址。
字段是动态内存地址存储,只能在运行时获取其值。
实例只读字段只能在实例构造器被赋值,实例初始化后执行,且执行一次;
静态只读字段只能在类型构造器中赋值,执行。
很多字段都是以内联方式进行初始化,实际上是在构造器中初始化的。
三、方法
1. 实例构造器
创建引用类型的实例,步骤:
首先为实例分配内存,初始化实例的附加成员,最后调用类型的实例构造器设置对象的初始状态。
每个实例构造器都会初始化字段,必须防止代码膨胀(设置一个显式初始化的构造器,其他构造器使用显式构造器初始化,有利的减少了代码)
值类型的构造器只有被显式调用时,才会执行。C#根本就不允许我们定义一个值类型的无参构造器。
2.类型构造器
类型构造器,默认情况没有定义,要定义也只能定义一个,并且是无参构造器。static,私有;值类型与应用类型都具有。
调用时机:
在类型的一个实例对象创建之前,或者在类型的第一个非继承的字段或者成员第一次访问之前;
在非继承静态字段被第一次访问之前的某个时刻;
类型构造函数不应调用基类构造函数;基类的静态字段并没有被派生类型继承。静态字段,静态方法,静态属性等都不会被继承,而是编译时静态绑定。
执行顺序:
首先产生初始化静态字段所需的代码,然后才是类型构造方法中显式的代码转换。与实例构造器执行顺序一致。
3.操作法重载方法
4.转换操作符方法
隐性转换操作符:Implicit Operator 类型A(int a);类型A aa = 3;
显性转换操作符:explicit Operator 类型Int(类型A a); int aa = (int)类型A 对象;
5. 引用参数
默认情况,CLR都是认为参数都是值传递;引用类型是传递引用或者指针(也是引用或者指针本身也是按值传递的);
对于值类型实例的参数,传递给方法的将是值类型实例的一份拷贝,意味着方法得到了属于他自己的值类型实例的拷贝;使用Out和Ref 关键字告诉编译器需要按照引用方式处理(即传入的是地址)。
Out 不需要再方法体外就被初始化,并且方法不能直接读取该参数的值,还必须返回前给其赋值;(输出)
Ref 需要在方法体外被初始化,方法体可以选择读取或者赋值操作。
不能通过Out与Ref来区别重载,因为其编译后代码一样。但是运行Out,Ref 与不带这两个关键字的方法重载。
6.可变数目参数
static Int32 Add(parmas Int32[ ] valuse);
Add(1,2,3,4);//编译通过
parmas 告诉编译器在指定的参数上应用一个System. ParmaArrayAttribute定制特性的实例。
7.虚方法的调用机理
call:根据引用变量的类型(引用变量的静态类型,声明类型)来调用一个方法;
callvirt:根据引用变量指向的对象类型(引用变量的动态类型,实际类型);
8.虚方法的版本问题
使用new, 告诉编译器,子类方法与基类没有关系;
使用override,告诉编译器,子类方法与基类方法相关;虚函数执行时,总是调用继承链中最后的实现。
四、属性
属性又叫索引器
1. 无参属性
2.含参属性
五、事件
定义了事件成员的类型运行类型(类型的实例)在某些特定事情发生的时候通知其他对象。
定义事件成员意味着类型为我们提供了一下三种能力:
允许对象登记该事件;
允许对象注销该事件;
允许定义事件的对象维护一个登记对象的集合,在事件发生时通知这些对象;
CLR事件机制是建立在委托机制上的,使用委托的回调机制。
1.发布事件
定义一个类型用于保存消息内容:
按约定需要继承 System.EventArgs,并且命名以EventArgs结束。
定义一个委托类型,用于指定事件触发时被调用的函数原型:
按约定需要以 EventHandler结束,void 返回值,object,EventArgs 参数。
定义一个事件成员:
event 委托名 mailmsg
定义一个受保护的虚方法,负责通知登记对象
OnMailMsg,如果有事件,则触发事件Mailmsg;
定义一个方法,将输入转化成期望的事件:
event 编译器翻译成三个构造:
构造一个私有委托,指向null;
构造一个添加方法;
构造一个删除方法;
2.侦听事件
+=操作符: 登记事件;(编译器提供了内置的事件支持 add_事件);
-=操作: 删除事件
3.显式控制事件注册
4.在一个类型中定义多个事件
使用EventHandlerset
5.设计EventHandlerSet类型 (略)