结束C#2的内容:最后一些新性
这是本章要讲的内容:
- 分部类型:可以在多个源文件中为 一个类型编写代码。 特别适用于部分代码是自动生成, 而其他部分的代码为手写的类型。
- 静态类:对工具类进行整理, 以便编译器能明白你是否在不恰当地使用它们, 并使你的意图更清晰。
- 独立取值方法/ 赋值方法属性:属性终于有了公有取值方法和私有赋值方法了!( 这不是唯一的组合, 不过这是最常见的组合。)
- 访问器
- 命名空间别名:在类型名称不唯一的情况下的一种解决方式。
- pragma指令:用于 操作 的 特定 编译器 指令, 如 禁止 对 某一 特殊 代码 段 使用 特定 的 警告 信息。
- 固定大小的缓冲区:在非安全代码中, 可以更多地控制结构处理数组的方式。
- 友元程序集:跨越语言、框架和运行时的一个特性, 在需要时能对选定的程序集进行更多的访问。
分部类型
简单来说就是C#2允许用多个文件来表示一个类型。用partial关键字来指定一个类是分部类型。
分部类型的规则:
- 不能在文件中编写成员的一半代码,而在另一个文件中编写成员的另一半,成员的代码必须完整的放在一个文件中。有一个例外是分部类型能够嵌套另一个分部类型。
- 任何文件都能指定要实现的接口(不过不必在那个文件中实现) 基类型以及类型参数约束。 然而, 如果多个文件都设定了基类型, 那么它们必须是相同的, 并且如果多个文件都设定了类型参数约束, 那么约束必须是一致的。
- 必须具有相同的访问修饰符。如果有的话。
- ”单文件“类型中,成员和静态变量的初始化一定会按照固定的顺序来进行。但是在分部类型中,就不一定了。
分部类型主要是和代码生成器一起配合使用,比如在Winform中的Form类。
分部类型还有一种稍微不同的用法, 就是辅助进行重构。 某些时候, 一个类型变得太大, 担当了太多职责, 就应对其进行重构。 重构的第一步就是要把这种臃肿的类型分成较小的类, 很多关联的内容首先就可以分割为在两个或多个文件上存放的分部类型。 接着, 我们在文件之间移动方法直到每个文件只处理一种特定的内容, 这个工作可以以一种毫无风险的实验方式来完成。
分部类型-->分部方法
分布方法与抽象方法的声明方式相同:用一个partial关键字来声明就行,不需要有方法体。当然,实现的方法同样也需要有partial修饰。
由于方法可能不存在,比如我在一个分部类中声明一个分部方法,但没有具体的去实现它,那么它在编译好的IL代码中将被清除掉,包括任何参数计算,所以,如果你的一些分部方法如果不确定是否要进行加载,那么就要用 分部方法(实例化后的参数)这样的形式来进行加载,以避免不必要的负荷。
同样由于方法可能不存在,分部方法的返回值必须是void,并且不允许有out修饰的参数。必须是私有的,但可以是静态或泛型的。
概括来说, C# 3的分部方法让生成代码可以和手写代码以一种丰富的方式进行交互, 而在无须这种交互的情况下不会产生任何性能损失。 C# 2分部类型可以让代码生成工具和开发人员之间的关系更富有成效, 而分部方法是对分部类型的一种自然延续。
静态类型
我们编写静态类型的主要目的就是编写一些工具类。工具类的主要特征如下:
- 所有的成员都是静态的( 除了私有构造函数);
- 类直接从object 派生; 一般情况下不应该有状态,
- 除非涉及高速缓存或单例;
- 不能存在任何可见的构造函数;
- 类可以是密封的( 添加sealed修饰符), 当然要开发人员记得这样做。
在C#1中是不能创建一个静态类的,因为没有语法上面的支持。如果我们要创建一个类似概念的东西,就得在类里面创建一个私有的构造方法,然后给类打上一个sealed的标签。添加一个私有的构造方法显得很搞笑,既然不能调用这个构造方法,为什么要添加它呢?问题在于如果没有显式的添加一个构造方法,编译器会为你免费的赠送一个public的无参的构造函数。
C#2可以创建静态类,也不用显式的添加一个私有的构造方法,因为编译器知道它是一个静态的类,不会给他提供默认的无参的构造函数。
应当注意的是静态类中的所有成员必须都是静态的。而且还有显式的声明为静态,除了嵌套类型和常量。
实际上,编译器在类定义上执行了大量的约束:
- 类不能声明为abstract或sealed, 虽然两者都是隐含声明的;
- 类不能设定任何要实现的接口;
- 类不能设定基类型;
- 类不能包含任何非静态成员, 包括构造函数;
- 类不能包含任何操作符;
- 类不能包含任何protected或protected internal成员。
独立的取值方法/ 赋值方法属性访问器
这个标题在C#1中是不成立的,取值和赋值必须拥有相同的访问修饰符。
这个呼声很高的特性最终在C#2被添加了上来,很明显这是一个常见的需求,在类的外部,我们的取值是可见的,但赋值的话要经过一些验证才能被赋值,这是大多数程序的逻辑。在类内,我们可以对传入的参数进行验证并最终给属性进行赋值的操作。这个实现了更好的封装。
你不能吧属性设置为私有而把取值和赋值设置成共有----这个就搞笑了。编译器也不会同意。
C#2依然没有组织内部的代码绕过属性直接访问字段,现在也没有实现。这都C#7了。
命名空间别名
命名空间的主要意图是将多个类型组织成一个有用的层级。我们有时会遇到两个非限定名相同的类型,比如一个是System.Windows.Form.Button,另一个是System.Web.UI.WebControls.Button。它们都叫Button。我们不可能一直用这种全限定名来使用一个类型,不论是可读性还是什么的都很糟糕,可以使用C#的using指令:using shit=System.Windows.Form.Button.我们在使用的时候,就用shit这个名称来代替System.Windows.Form.Button。
后面几个书上将的特性我根本没遇到,不往上面写了。