静态构造:
静态构造方法是每个类执行一次,而不是每个类实例执行一次。一个类只能定义一个静态构造方法,并且必须没有参数,必须和类同名,
运行时在使用类之前自动调用静态构造方法,下面两种行为可以触发静态构造方法:
1、实例化类
2、访问类的静态成员
静态构造方法只有两个修饰符:unsafe和extern
注:如果静态方法抛出一个未处理异常,类在整个应用程序的生命周期内都是不可用的。
静态构造方法和字段初始化顺序:
静态字段在调用静态构造方法之前执行初始化。如果一个类没有静态构造方法,字段在类被使用前初始化或在运行时随机选一个更早的时间执行初始化(这说明静态构造发放的存在可能使字段初始化比正常时间晩执行)。
静态类:
类可以被标记为staic,表明它必须由静态成员组成,并且不能产生子类。System.Console和System.Math就是静态类的最好示例。
局部类:
局部类允许一个类分开定义,典型的用法是分开在多个文件中。从其他源文件自动生成的类需要和自定义的方法交互时,通常使用partail类
每个部分必须由partial声明
局部类的各组成部分不能有冲突的成员。例如具有相同参数的构造方法,不能重复出现。局部类完全由编译器处理,也就是说,各组成部分在编译时必须可用,并必须编译在同一个程序集中。
每个部分都可以独立定义并实现接口
局部方法:
局部类可以包含局部方法,这些方法使自动生成的局部类可以为自定义方法提供自定义钩子(hook)
例:
public partial class ParticalTest
{
partial void CreateInt(int a);
}
//另一个
public partial class ParticalTest
{
partial void CreateInt(int a)
{
if (a > 0)
{
return;
}
}
}
局部方法由两部分组成:定义和实现。定义一般由代码生成器产生,而实现多为手工编写。如果没有提供方法的实现,方法的定义会被编译器清楚。这使得自动代码可以自由提供钩子,而不用担心代码过于臃肿。局部方法必须是void型,并且默认为private的
继承:
为了扩展或自定义原类,类可以继承另一个类。继承类让你可以重用另一个类的方法,而无需重新构建。一个类只能继承自唯一的类,但可以被多个类继承,从而形成类的层次
多态:
多态性之所以能实现,是因为子类具有基类的全部特征。反过来,则不正确
隐藏继承成员:
基类和子类可能定义相同的成员,例如
public class A
{
public int Counter = 1;
}
public class B:A
{
public int Counter = 2;
}
当B中的字段Counter隐藏了类A中的字段Counter。通常,这种情况的产生是由于编程时,在定义子类的成员之后又把相同的成员加到基类中。因此,编译器会产生一个警告,可以用下面的方法避免二义性:
1、A类的引用(在编译时)绑定到A.Counter
2、B类的引用(在编译时)绑定到B.Counter
有时需要故意隐藏一个成员,这种情况下,可以在子类中使用new修饰符。new修饰符的作用仅为防止编译器发出警告
public class A
{
public int Counter = 1;
}
public class B:A
{
public new int Counter = 2;
}
密封方法和类:
重载的方法成员可用sealed关键字密封它的实现,以防止该方法被它的更深层次的子类再次重载
也可以在类中使用sealed修饰符来密封整个类,含义是密封类中所有的虚方法。
base关键字:
关键字base和this很类似,有下面两个重要目的
1、从子类访问重载的基类方法成员
2、调用基类的构造方法
装箱和拆箱:
装箱是将数值类型转换成引用类型实例的行为。引用类型可以是object类或接口。
拆箱操作正好相反,它把object类型转换成原始的数值类型。
装箱和拆箱的实质是复制:
装箱是把数值类型的实例复制到新对象中,而拆箱是把对象的内容复制回数值类型的实例中。
GetType和typeof运算符:
所有的C#类型在运行时都会维护System.Type类的实例。有两个基本方法可以获得System.Type对象:
1、在类实例上调用GetType方法
2、在类名上使用typeof运算符
GetType在运行时赋值,typeof在编译时静态赋值(如果使用泛型类型,name它将由即时编译器解析)。
ToString方法:
ToString方法返回类实例的默认文本表述,这个方法被所有的内置类型重载。
注:当直接在数值型对象上调用像ToString这样的重载的object成员时,不会发生装箱;只有进行类型转换时,才会执行装箱操作。
var和dynamic:
var和dynamic类型表面上是相似的,但是它们实际上是有区别的:
var由编译器确定类型。
dynamic由运行时确定类型。
dynamic x = "hello";//静态类型是dynamic,运行时类型是string
var y = "hello";//静态类型是string,运行时类型是string
int i = x;//运行时错误
int j = y;//编译时错误
一个由var声明的变量的静态类型可以是dynamic:
dynamic x = "hello";
var y = x;//y的静态类型是dynamic
int z = y;//运行时错误