CLR via C# 笔记——第八章

方法

《CLR via C#》第八章:方法

实例构造器和类(引用类型)

构造器是将类型的实例初始化为良好状态的特殊方法,在方法定义元数据表种始终叫做.ctor
创建引用类型的实例会:
1 为实例的数据字段分配内存
2 初始化对象的附加字段(类型对象指针和同步块索引)
3 调用类型的实例构造器来设置对象的初始状态。

实例构造器无法被继承。默认定义一个无参构造器。
如果类为abstract,默认构造器的可访问性为protected。
如果基类没有提供无参构造器,派生类必须先是调用一个基类构造器。
如果类为static,则不会在类中生成默认构造器。

实例构造器和结构(值类型)

CLR总是创建值类型的实例。值类型不需要定义构造器。
值类型允许定义构造器,但必须显示调用才会执行。
C#不允许为值类型定义无参构造器。

类型构造器

又称为静态构造器、类构造器、类型初始化器。可以应用于接口、引用类型、值类型。
类型构造器永远没有参数。
类型构造器必须标记为static,并且总是私有。
类型构造器代码中只能访问类型的静态字段,常规用处即是用于初始化这些字段。

操作符重载方法

CLR规范要求操作符重载方法必须是public和static的。

1
2
3
4
public seled class Complex {  
public static Complex operator+ (Complex c1, Complex c2) { ... }
public static Complex Add(Complex c1, Complex c2) { return (c1+c2); }
}

转换操作符方法

如果源类型或目标类型不是基元类型,编译器会生成代码,要求CLR执行转换(强制转型)。
转换操作符是将对象从一种类型转换成另一种类型的方法。
CLR规范要求转换操作符方法必须是public和static的。
C#要求参数类型和返回类型至少有一个与定义转换方法的类型相同。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
public seled class Rational {  
// 由一个Int32构造一个Rational
public Rational(Int32 num) { ... }
// 由一个Single构造一个Rational
public Rational(Single num) { ... }
// 将一个Rational转换成一个Int32
public Int32 ToInt32() { ... }
// 将一个Rational转换成一个Single
public Single ToSingle() { ... }

// 由一个Int32隐式构造并返回一个Rational
public static implicit operator Rational(Int32 num) {
return new Rational(num);
}
// 由一个Single隐式构造并返回一个Rational
public static implicit operator Rational(Single num) {
return new Rational(num);
}
// 由一个Rational显示返回一个Int32
public static explicit operator Int32(Rational r) {
return r.ToInt32();
}
// 由一个Rational显示返回一个Single
public static explicit operator Subgke(Rational r) {
return r.ToSingle();
}
}

在C#中,implicit关键字告诉编译器为了生成代码来调用方法,不需要再源代码中进行显示转型。explicit关键字告诉编译器,只有再发现了显示转型时,才调用方法。

扩展方法

允许定义一个静态方法,并用实例方法的语法来调用。

public static class StringBuilderExtensions{
    public static Int32 IndexOf(this StringBuilder sb, Char value){
        for(Int32 index = 0; index < sb.Length; index++)
            if(sb[index] == value) return index;
        return -1;    
    }
}

扩展方法的附加规则和原则:

  • C#只支持扩展方法,不支持扩展属性、扩展事件、扩展操作符等。
  • 扩展方法必须在非泛型的静态类中声明。扩展方法至少有一个参数,并且只有第一个参数能用this关键字标记。
  • C#编译器在静态类中查找扩展方法时,要求静态类本身必须具有文件作用于。(不能是嵌套类)
  • 多个静态类可以定义相同的扩展方法。
  • 一个扩展方法扩展一个类型的同时也扩展了派生类。
  • 扩展方法可能存在版本问题(后续版本添加了对应的实例方法)。
    扩展方法实际是对一个静态方法的调用。

分部方法

internal sealed partial class Base{
    // 分部方法声明
    partial void OnNameChanging(String value);
}
// 另一个源代码文件  
internal sealed partial class Base{
    partial void OnNameChanging(String value){
        // ...    
    }
}

分部方法的规则和原则:

  • 只能再分部类或结构中声明
  • 分部方法返回类型始终未void,任何参数都不能用out修饰符来标记。
  • 分部方法可以有ref参数,可以是泛型方法,可以是实例或静态方法,可以标记未unsafe。
  • 分部方法的声明和实现必须具有完全一直的签名。
  • 没有对应的实现部分,就不能在代码中创建一个委托来引用这个分部方法。
  • 分部方法总是被视为private方法。