CLR Via C# 3rd 阅读摘要 -- Chapter 8 - Methods
Instance Constructors and Classes(Reference Types)
1. 实例构造方法编译成IL在方法定义元数据表中就是.ctor;
2. 当创建一个引用类型的实例时,先是分配内存(数据字段、头部字段[类型对象指针和同步块索引]),然后就调用.ctor;
3. 实例构造器不能用修饰符:virtual, new, override, sealed, abstract;
4. 如果类是abstract的,那么编译后的默认构造器就是protected;
5. 如果类是static的(seaded+abstract),编译器不会产生默认构造器.ctor;
6. 不能在构造器中调用任何虚拟方法,因为子类会覆盖该方法,而该方法可能会使用尚未被初始化的字段。
Instance Constructors and Structures(Value Types)
1. struct不同于class,值类型实际上并不需要定义一个构造器,C#编译器不会生成(也不允许定义CS0568)无参数的默认构造器;为什么?性能!
2. 严格的讲,引用类型中定义的值类型字段可以保证为0/null,而基于栈的值类型字段不能保证是0/null;
3. 虽然C#不支持值类型无参数的构造器,但是CLR支持。所以在C#中值类型中的实例字段内联初始化是不可以的,但是静态字段是可以的;
4. 在C#中,值类型可以有带参数的构造器,但是,在构造器返回前,必须将所有字段赋值。
Type Constructors
1. 类型构造器也叫:静态构造器,类构造器,类型初始化。生成的是.cctor;
2. 类型构造器可以用于接口(但是C#可不支持)、引用类型、值类型;
3. 类型构造器不能有参数;
4. 虽然值类型可以有类型构造器,但实际上你可别这么干,因为有时候值类型的类型构造器并不会被调用;
5. 类型构造器是多线程安全的;
6. CLR不支持static Finalize方法。但是可以注册System.AppDomain.DomainUnload事件。
Operator Overload Methods
1. C#的一元操作符;
2. C#的二元操作符;
3.在FCL中,核心的值类型(Int32, Int64, UInt32, ...),并没有定义任何操作符重载方法。原因是性能!
Conversion Operator Methods
1. static implicit/explicit operator。生成的方法op_Implicit或op_Explicit;
2. 举例,注意implicit和explicit不同:
public Rational(Int32 num) { ... }
public Rational(Single num) { ... }
public Int32 ToInt32() { ... }
public Single ToSingle() { ... }
public static implicit operator Rational(Int32 num) {
return new Rational(num);
}
public static implicit operator Rational(Single num) {
return new Rational(num);
}
public static explicit operator Int32(Rational r) {
return r.ToInt32();
}
public static explicit operator Single(Rational r) {
return r.ToSingle();
}
}
3. 在Rational类型的元数据中,4个转换操作方法看起来是这样的:
public static Rational op_Implicit(Single num)
public static Int32 op_Explicit(Rational r)
public static Single op_Explicit(Rational r)
4. C#在使用转换表达式时显示的调用op_Explicit,但是在使用as 或 is时不会被调用;
5. 理解操作符重载和转换操作方法最好的途径就是研究Decimal。
Extension Methods
1. 扩展方法就是为一个已有类型添加方法,而不需要修改现有的类型(Decorate Pattern);
public static Int32 IndexOf(this StringBuilder sb, Char value) {
...
}
}
2. 规则和指南:
- C#只支持扩展方法,可没有什么扩展属性、扩展事件、扩展操作符等等;
- 扩展方法必须定义在非泛型的static类中,并且该类必须是顶级的,而不能是其他类型的内部类;
- 为了改进性能和避免混淆,在代码用使用扩展方法时,必须首先import提供该扩展的名称空间;
- 可别滥用扩展方法;
- 扩展方法存在潜在的版本问题。
3. 可以为接口类型提供扩展方法,也可以为委托类型提供;
4. 这里不能不提到LINQ。
Partial Methods
1. partial方法只能定义在partial class或partial struct中;
2. partial方法的返回类型必须是void,并且不能有任何out修饰的参数;
3. partial方法必须有一致的声明;
4. 如果一个delegate引用一个partial方法,而该partial方法没有实现,那么会产生编译错误CS0762;
5. partial方法总是考虑设置成private的。 但是C#禁止在partial前加个访问修饰符,包括private。
本章小结
本章的焦点是开发过程中会用到的各种方法,包括实例构造器、类型构造器(静态构造)、操作符重载、类型转换方法。最后讨论了扩展方法,也就是怎么在现有类型中加入方法(Decorate Pattern) ,还有将功能的实现代码分别放在不同文件中的部分方法。