1.虽然并不是必需的,但一般建议将每个类都放到它自己的文件中,用类名对文件进行命名,这样一来,就可以更容易地寻找定义了一个特定类的代码。
2.如果不为类成员添加访问修怖符,那么黠认使用的是private,也就是说成员默认为私有成员。
3.不管为私有字段使用哪一种命名模式(_FirstName、_firstName、m_firstName(延续子C++的命名规范,m表示 member variable)、firstName),都要依据Pascal大小写规范来命名公共字段和属性。因此,公共属性应该使用FirstName形式的名称,类似地,假如没有围绕一个公共字段来创建封装它的一个属性,就应该为该字段使用Pascal大小写规范。
4.在C#2.0的一个属性的实现中,可以为get或者set部分指定访问修饰符(但不能为两者同时指定访问修怖符),从而覆盖为属性声明指定的访问修饰符。为get或set指定访问修饰符时,注意这个访问修饰符的“限制性”必须比应用于整个属性的访问修饰符更“严格”,例如,将属性声明为较严格的 private,但将它的set声明为较宽松的public,就会发生编译错误。
5.对象初始化器只是一项语法上的改进,最终生成 ClL 代码和用单独的语句对字段或属性进行赋值无异,在c#语言中,成员初始化器的顺序,决定了在 ClL 代码的构造器调用之后的语句中,对属性和字段进行赋值的顺序。同理集合初始化器也会在IL中生成add()来添加元素。
6.终结器:C#提供了终结器 (finalizer) 构造,与 C++的析构器 (destructor ) 不同,终结器不是在对一个对象的所有引用都消失之后就马上运行,相反终结器是在一个对象最后一次活动之后,并在程序终止之前执行。具体地说垃统回收器回在-次垃圾回收过程中识别出带有终结器的对象,之后它并不是立即回收这些对象,而是将它们添加到一个终结队列中,一个独立的线程遍历终结队同中的每个对象,调用它们的终结器,鼎后把它们从队列中删除,使它们再次可供垃圾回收器使用。
7.构造器链:在同一个类中{针对同一个对象实倒),从一个构造据中调用另一个构造嚣,C#采取的语法格式是在个冒号后面添如this关键字,再添加与披调用构造器对应的一个参数列表。以避免输入重复的代码,这称为构造器链(constructor chaining),它是用构造器初始化器来实现的,构造器初始化器会在执行当前构造器的实现之前,判断要调用另外哪一个构造器。
8.匿名类型:它们是由编译器动态生成的数据类型,而不是通过显式的类定义来声明的。使用new{属性=,属性=,值}(如果所赋的值是一个属性或字段,那么在没有明确指定名称的前提下,会黠认使用字段或属性的名称),编译器遇到匿名类型的语法时,就会自动生成一个CIL类,该类具有与匿名类型声明中的命名值和量据类型对应的属性,虽然C#没有为这个自动生成的类型提供一个名挥,但它仍然是静态类型的。除非使用Lambda表达式和查询表达式关联来自不同类型的数据,或者对数据进行水平投射,否则一般情况下还是应该尽量避免使用匿名类型。
9.静态类的一个特证在于,C#编译器会自动在 CIL代码中把它标记为 abstract 和 sealed 这会将类指定为不可扩展。
10.静态构造器:静态构造器用来对类(而不是类实例)进行初始化,静态构造器不是显式调用的,相反“运行时”会在首次访问类时自动调用静态构造器,所谓“首次访问类”可能是调用一个普通实例构造器,也可能是由问类的一个静态方法或属性,我们使用静态构造器将类中的静态数据初始化成一个特定的值,尤其是在无法通过在声明时的一次简单的赋值来获得初始化值的时候。假如一个静态字段的赋值,既在静态构造器中进行,又在声明时进行,那么当初始化结束的时候,最终获得的是什么值呢?
答案是静态初始化的赋值优先于声明字段时的赋值,因为在C#编译器生成的IL码时,静态声明时的赋值移动到了静态构造器的第一句。同理实例字段的情况也是一样的。
11.常量const:常量字段自动成为静态字段,因为不需要为每个对象实例都生成一个新的字段实例,但是假如将一个常量字段显式地声明为 static,会造成一个编译错误。
12.嵌套类:在某个类对外部没有使用、或特别意义,只对当前的类有意义,可以声明为嵌套类,嵌套类可是用private修饰。嵌套类中的this成员指的是嵌套类的一个实例,而不是包容类,嵌套类要想访问包容类的实例,一个办法是显示传递包容类的实例,比如通过一个构造器或这方法参数。嵌套类的另一个有趣的特点是它能够访问包容类的任何成员,其中包括私有成员。但反之则不然,包容类不可能访问嵌套类的私有成员。要警惕public嵌套类,它们意味着不良的编码风格。
13.部分类与部分方法:部分类(partial calss)主要用于代码生产工具进行固定格式代码生成,部分类的声明可以把多个部分类放在多个文件中(必须在同一个程序集中),编译器会自动合并。
C#3.0新增了部分方法(partial methods)特性,部分方法只能存在于部分类中,且无返回值,和部分类相似,其主要是为代码的生成提供方便。部分方法允许声明一个方法而不需要一个实现,然而如果包含了可选的实现,这个实现就可以放到某个姊妹部分类定义中。因为在生成的部分类代码中,生成工具不能提供具体方法实现逻辑,若以部分方法的形式提供一个钩子(占位),具体实现可由开发者实现,若部分方法没有在另一个部分类中实现,IL中不会出现部分方法的任何踪迹。如在Person类中展示了部分方法与部分类的细节。
//Person.Designer.cs文件 public partial class Person { #region partial void OnLastNameChanging(string value); partial void OnFirstNameChanging(string value); #endregion public Guid Id { get; set; } private string _LastName; public string LastName { get { return _LastName; } set { if (_LastName != value) { OnLastNameChanging(value); _LastName = value; } } } private string _FirstName; public string FirstName { get { return _FirstName; } set { if (_FirstName != value) { OnFirstNameChanging(value); _FirstName = value; } } } } //Person cs文件 public partial class Person { partial void OnLastNameChanging(string value) { if (string.IsNullOrWhiteSpace(value)) { throw new ArgumentException("LastName"); } } partial void OnFirstNameChanging(string value) { if (string.IsNullOrWhiteSpace(value)) { throw new ArgumentException("FirstName"); } } }
-------------------------以上内容根据《C#本质论 第三版》进行整理