前言
本篇我们继续讲解本章其余的部分:构造函数、只读字段、匿名类型、结构详解、部分类、静态类、Object类、扩展方法,等。
01
类
构造函数
构造函数是一种特殊的方法:
当我们把构造函数看成方法后,构造方法间的互调用,我们可能会认为和方法一样,比如:
TestMain(){
}
TestMain(int arg){
this(); //构造方法互调用
int a = 10;
}
但实际上,这种方法只适用于Java(且构造方法的调用必须在首行)。在.Net中,使用的是叫做“构造函数初始化器”的语法:
Test()
: base() //调用基类的初始化器
{
}
Test(int arg)
:this(arg, 5) //初始化器
{
arg = 10;
}
Test(int arg1, int arg2)
:this() //初始化器
{
}
构造函数初始化器在构造函数函数体执行之前执行。this为类的多个构造函数的互调用,base为对基类的构造函数的调用。
只读字段
只读字段(readonly)是对常量的补充。
private readonly int Column5;
它的应用场景是:允许把一个字段设置为常量,但还需要执行一些计算,以确定它的初始值,这是常量无法做到的。
它的规则是:可以在构造函数中给只读字段赋值,但不能在其他地方赋值。
匿名类型
之前的章节,见过使用var关键字实现“类型推断”,var同时还应用于创建匿名类型。所谓匿名类型,是是一个继承自Object且没有名称的类。
var obj = new
{
Name = "daixf",
Age = 40
};
我们可以看到,在定义匿名类型时,需要指定属性名称和值。注意匿名类型的成员是属性而不是字段,可以想想为什么这么设计?我想,是因为遵循设计规范,属性一般是public的,而字段一般是private,两者各司其职。显然匿名类的成员需要被访问,所以应该是public,所以应该定义为属性。
但不是任何情况下,都需要指定创建的匿名类型的属性名的,如果数据来自于其他类的属性,匿名类型会默认使用相同属性名。
var obj1 = new
{
obj.Name,
obj.Age
};
因为匿名类型并没有特定的类型名,编译器为其指定了一个临时的类型名,因此在匿名类型上无法执行反射功能。
结构
上一篇已经讲过,结构和类非常像。结构的特点:
部分类(partial)
部分类似乎离我们很远,我在践行“基于Repository框架”的时候,曾经必须用它,因为大量的类需要通过工具软件生成,而工具生成的类又有一部分功能需要手工书写,为了避免手工写的代码被工具软件覆盖,所以就采用了部分类的方式,一个类分为两个文件。但抛弃了Repository框架之后,我就再也没有主动用过部分类。
采用部分类的原因一般有以下几种:
使用部分类的一个典型就是Winform窗体。一些初学者可能还不知道Form窗体使用了部分类。一个Form窗体就有两个cs代码文件,designer.cs就是由界面设计工具生成的:
使用部分类遵循的规则:
除了部分类,还有“部分方法”的概念,用途差不多,这里先不详述。
静态类(static)
是否定义类为静态类,似乎并不是那么清楚。因为一般我们声明一个静态字段/属性,或者实现一个静态方法,也不代表其所在的类必须是静态类。那么我们什么情况下认为类应该定义为静态类呢?我认为是否定义为静态类,更多的依据编程规范,而不是强制要求。
Object类
所有.Net类都派生自Object类,包括结构(结构首先派生自类System.ValueType,而ValueType类又派生自Object类)。结构也派生自类,这也就好理解为什么struct的定义和class这么像了。
Object作为基类,它的一些成员是都是非常重要的,而且非常常用,简单介绍:
扩展方法
扩展方法应用于:想给某个类增加方法,但却没有类的源码,或者没有对类的修改权限。此时可以使用扩展方法。扩展方法是静态类中的静态方法。对于扩展方法,第一个参数是要扩展的类型,它放在this关键字的后面。这告诉编译器,这个方法是扩展类型的一部分。在这个例子中,string是要扩展的类型。
public static bool IsNullOrEmpty(this string str)
调用:"abc".IsNullOrEmpty()
第三章到此为止就结束了,本章总体上讲了类的组成成员,以及其字段、属性、方法,和各种特性。下章将讲解《继承》。
觉得文章有意义的话,请动动手指,分享给朋友一起来共同学习进步。
欢迎关注本人微信公众号,更及时的关注最新文章(每周三篇原创文章,以及多篇专题文章):
附文:
c#静态构造函数 与 构造函数
C#部分类与部分方法
上一篇:解读经典《C#高级编程》第七版 Page68-79.对象和类型.Chapter3