NET CLR via C#读书笔记 - 第八章 方法
1 实例构造器与引用类型(类)
① 构造器是将类型实例初始化为良好状态的特殊方法。
② 元数据表中名字为.ctor
③ 创建引用类型时,首先为实例的数据字段分配内存并将分配的内存字节初始化为0,其次初始化附加字段(类型对象指针和同步块索引),最后调用实例构造器初始化数据字段来设置对象的初始状态。
④ 实例构造器无法被继承,无法使用abstract,sealed,virtual等修饰符修饰。
⑤ 类没有定义实例构造器,C#编译器会默认创建一个实例构造器,默认的实例构造器不会执行任何操作。
⑥ 类的实例构造器默认为public,如果类由abstract修饰,则实例构造器的可访问性为protected。静态类不会生成默认的实例构造器。
⑦ 可定义多个实例构造器,只要每个实例构造器的方法签名不同即可。
⑧ 使用内联初始化时要注意代码膨胀效应。
2 实例构造器和值类型(结构)
① C#编译器不会为值类型生成默认实例构造器。
② 值类型的字段总是被初始化为0或者null。
③ 不能在值类型中使用内联初始化。
3 类型构造器
① 类型构造器又叫静态构造器,用于设置类型的初始状态。
② 类型构造器最多只能实现一个,可以不实现,且类型构造器永远没有参数。
③ 类型构造器在C#中可在值类型和引用类型中定义,必须由static修饰,代码如下:
//引用类型的类型构造器形式
internal sealed class classdemo{
static classdemo(){}
}
//值类型的类型构造器形式
internal struct structdemo{
static structdemo(){}
}
④ 类型构造器总是private的,且程序员不能显示修饰为private,由C#编译器来进行默认处理。
⑤ 类型构造器的调用过程比较麻烦,需要记住的一点就是线程同步问题,类型构造器只会调用一次。这些工作都由CLR完成,程序员无需关心。
⑥ 类型构造器只能访问类型的静态字段。
4 操作符重载方法
① 部分语言允许类型定义操作符应该如何操作类型实例,但是CLR本身是对操作符一无所知,CLR只是定义了编程语言公开操作符的方法,在CLR眼里,操作符也只是一个方法而已。操作符的含义由编程语言定义,以及当操作符出现时应当生成怎样的代码。
② 操作符重载函数必须是public和static。
③ C#允许重载的一元和二元操作符如下:
一元操作符
二元操作符
⑤ 操作符重载代码演示如下:
public sealed class complex{
public static complex operator+(complex c1 , complex c2){}
}
5 转换操作符方法
5.1 转换操作符方法描述
① 用于一种类型转换为另一种类型的方法,C#编译器知道如何生成基元类型间的转换。
② 转换构造器和转换操作符方法定义代码如下:
using System;
public sealed class Demo{
//转换构造器 只有一个参数 且参数要求为待转换源类型的实例
public Demo(Int32 i){} //由一个Int32构造一个Demo
public Demo(Single s){} //由一个Single构造一个Demo
//转换方法 没有参数
public Int32 ToInt32(){} //将一个Demo转化为Int32
public Single ToSingle(){} //将一个Demo转化为Single
}
5.2 转换操作符方法重载
① 将5.1中代码部分进行扩展,来演示装换操作符重载:
using System;
public sealed class Demo{
//转换构造器 只有一个参数 且参数要求为待转换源类型的实例
public Demo(Int32 i){} //由一个Int32构造一个Demo
public Demo(Single s){} //由一个Single构造一个Demo
//转换方法 没有参数
public Int32 ToInt32(){} //将一个Demo转化为Int32
public Single ToSingle(){} //将一个Demo转化为Single
//转换操作符方法重载
//由Int32类型隐式构造并返回一个Demo
public static implicit operator Demo(Int32 i){
return new Demo(i);
}
//由Single类型隐式构造并返回一个Demo
public static implicit operator Demo(Single s){
return new Demo(s);
}
//由demo类型返回一个Int32
public static explicit operator Int32(Demo d){
return d.ToInt32();
}
//由demo类型返回一个Single
public static explicit operator Single(Demo d){
return d.ToSingle();
}
}
说明:implicit告诉编译器不需要生成代码来显示转换,explicit只有发生了显示转型时才调用代码。
6 扩展方法
① 扩展方法运行定义一个静态方法并使用实例方法的语法进行调用,使用this进行标注。
② 扩展方法的代码示例如下:
public static class ExDemo{
public static void Demo(this int i,char c){}
}
③ 结合上述代码示例,说明扩展方法的一些使用规则和相关原则:
第一,C#只支持扩展方法,不支持扩展字段,扩展事件,扩展属性,扩展操作符等。
第二,必须在非范型的静态类中声明,有且只有包含一个用this修饰的参数。
第三,必须具有文件作用域,不能是嵌套类。
第四,C#编译器要求导入扩展方法,以提高编译效率
第五,多个不同的静态类可以定义相同的静态方法,如果存在两个满足匹配的扩展方法,编译器会报错,此时要么修改源代码解决冲突,要么显示调用静态方法的方式调用(不能再用实例方法的调用方式进行调用)
第六,如果使用扩展方法扩展了一个基类,那么相应的派生类也都会被扩展,所以不要将System.Object作为this修饰的参数。
第七,版本控制,一开始由于不支持某一功能而实现了扩展方法,后续版本更新中,增加了相应的实例方法,此时会导致前后行为差异,可能会引发相关问题。
扩展方法还可扩展各种类型,接口,枚举,委托等都可以进行扩展,具体描述请查阅《NET CLR via C# 第四版》 第八章内容。
7 分部方法
① 分部方法的应用场景:想定制类型的某些行为,但是又不想通过继承和虚函数的方式去实现。
② 分部方法的规则和原则:
第一,只能在分部类和分部结构中声明。
第二,返回值只能是void,无法使用out修饰符,但可以有ref参数,可以是范型方法,可以是实例或者静态方法,也可以标记为unsafe。
第三,分部方法的声明和实现需要具有完全一致的签名。
第四,如果分部方法没有实现,那不不能创建委托来引用该分部方法。没有实现分部方法,C#编译器不会生成现任何分部方法相关的元数据。
第五,总是private,禁止程序员显示指定为private。
以上内容为对《NET CLR via C#(第四版)》第八章内容的阅读笔记,只记录其中核心部分内容,书中对以上主题还进行详细的代码演示说明,如需要详细阅读请自行查阅本书第八章内容,感谢您的阅读。