第八章 方法

1. 值类型的实例构造器

struct Point
{
    public int x, y;
    public Point(int x, int y)
    {
        x = x;
        y = y;
    }
}

值类型的构造器只有在使用New显式调用的时候才会执行.如果只是声明而没用使用New调用构造器,字段会是默认值0.

struct Point
{
    public int x, y;
    public Point()
    {
        x = 10;
        y = 11;
    }
}
Point pt;

那么Point中的XY字段仍旧是0,而不是10和11.值类型的无参默认构造器许多编译器是不会生成调用代码的.

C#的编译器故意不允许定义值类型的无参数构造器,以避免此问题引起迷茫…但是CLR是允许的.

为了生成可验证的代码,在访问值类型的任何一个字段之前都需要对全部字段进行赋值.

struct Test
{
    //private int t1 = 10;
    private static int t2 = 12;
}

第一行代码是编译不过的,第二行可以.C#不允许值类型为实例字段使用内联字段初始化语法,但静态字段可以.

2. 类型构造器 静态构造函数

设置类型的初始状态,类型默认没有类型构造器,如果定义只能定义一个,且没有参数.

必须是static ,自动标记为Private.

多个线程可能同时调用类型的类型构造器,CLR会要求在调用类型构造器时,调用线程要获取一个互斥线程同步锁.

在IL代码中类型构造器称为.cctor.

System.Runtime.CompilerServices.RuntimeHelpers.RunClassConstructor提供一组为编译器提供支持的静态方法和属性。此类不能被继承.可以调用基类的类型构造器.

如果希望在APPDomain卸载时执行一些代码,可以再System.AppDomain类型的DomainUnload事件登记回调方法.

3. 类型构造器的性能

C#编译器对进行内联初始化的静态字段,会在类的类型定义表元数据中添加BeforeFieldInit的记录项,如果看到显示的类型构造器就不会添加这个标记.对于显示的类型构造器要花费较多的时间进行处理,没有第一个性能高.

4. 操作符重载 转换操作符

对于CLR,操作符重载只是方法而已.

操作符重载方法必须是Public和Static,必须包含一个与当前类型相同的参数.

5. 扩展方法

C#只支持扩展方法不支持扩展属性等.

C#编译器在查找静态类中定义的扩展方法时,要求这些静态类本身必须有文件作用域,

如果存在多个相同的扩展方法,需要使用静态方法语法显示调用扩展方法.

扩展方法是静态方法,CLR在调用时会生成Call指令,不检查是否为Null

可以为接口定义扩展方法,只要实现了接口就可以调用.

扩展方法会被添加ExtensionAttribute属性,在元数据中标示含有扩展方法的程序集和类.这样在查找静态方法时就比较快了.

6. 分部方法

分部方法只能在部分类和结构中声明.

分部方法的返回值必须是Void,不能带有Out参数.因为方法在运行时可能不存在.(如果没有实现分部方法,编译器不会生产任何代表分部方法的元数据)

在代码生成工具中常见.

原文地址:https://www.cnblogs.com/zhangliming/p/3465216.html