1. C# 有两种类型的常量:编译时常量和运行时常量。html
2.尽可能使用运行时常量,而不是编译时常量。编程
/// <summary> /// 编译时常量 /// </summary> public const int Num = 100; /// <summary> /// 运行时常量 /// </summary> public static readonly int Year = 2017;
3.编译时常量只能用于数字和字符串,运行时常量也是一种常量,由于在构造函数执行后它不能被再次修改。安全
4.const 比 readonly 效率高,但灵活性低。框架
1.as 比强转更加高效、安全。函数
2.as 操做符不能配合值类型使用,由于值类型永远不可能为 null。post
public static void Test() { string msg = null; #if DEBUG msg = "Hi"; #endif Console.WriteLine(msg); }
假如你是将这块代码在 Release 版本中执行的话,就会输出空行。出现 Bug 的缘由是咱们把程序中的主要逻辑代码和条件编译代码混在一块了。这会让咱们很难察觉不一样版本间的差别,致使错误的行为发生。优化
1.应该为类型提供一个合适的 ToString() 版本,不然使用者会根据类的一些属性来自行构造并用于显示。ui
2.object 默认提供的 ToString() 方法会返回类型的完整名称,意义不大。如:System.Drawing.Rect。spa
3.重写全部类型的 ToString(),能够简单明了的显示对象的摘要信息。设计
1.系统提供 4 种函数判断两个对象是否“相等”。
2.对于前两种方法,咱们永远不要从新定义,咱们一般要重写 Equals 方法。
3.重写 Equals 的类型也要实现 IEquatable<T>,若是是结构体的话须要实现 IStructuralEquatable。
4.引用同一个 DataRow,会认为相等,若是想比较内容的话,而不是引用地址,那么就应该重写 Equals() 实例方法。
5.Equals() 实例方法的重写原则:对于全部的值类型,都应该重写 Equals() 方法,对于引用类型,若是不能知足须要时才去重写该方法。重写该方法的同时也须要重写 GetHashCode() 方法。
6.operator == ():只要建立的是值类型,都必须从新定义 operator == (),由于系统默认是经过反射来比较两个值是否相等,效率太低。
1.对于咱们实现的大多数类型来讲,避免实现 GetHashCode()。
2.GetHashCode() 的重载版本必须遵循如下三条原则:
(1)若是两个对象相等(由 operator == 定义),那么它们必须生成相同的散列码。
(2)对于任何一个对象 A,A.GetHashCode() 必须保持不变。
(3)对于全部的输入,散列函数应该在全部整数中按照随机分布生成散列码。
示例:
//1.使用循环 var foo = new int[100]; for (int i = 0; i < 100; i++) { foo[i] = i * i; } //使用查询语法 var foo2 = (from n in Enumerable.Range(0, 100) select n * n).ToArray();
1.有些方法语法没有对应的查询语法,如 Take、TaskWhile、Skip、SkipWhile、Min、Max 等,就须要使用方法语法。
1.对于程序集的第一次发布,能够随意使用可选参数和命名参数。而在进行后续发布时,必须为额外的参数建立重载。这样才能保证如今的程序仍能正常运行。此外,在任何的后续发布中,都要避免修改参数的名称,由于参数名称已经成为公有接口的一部分。
1.咱们最好尽量地编写出最清晰的代码,将优化工做交给 JIT 完成。一个常见的错误优化是,咱们将大量的逻辑放在一个函数中,觉得这样能够减小额外的方法调用开销。
public string Test(bool isTrue) { var sb = new StringBuilder(); if (isTrue) { sb.AppendLine("A"); sb.AppendLine("B"); sb.AppendLine("C"); } else { sb.AppendLine("E"); sb.AppendLine("F"); sb.AppendLine("G"); } return sb.ToString(); }
在第一次调用 Test 方法时, if-else 的两个分支都被 JIT 编译,而实际上只须要编译其中一个,修改后:
public string Test2(bool isTrue) { var sb = new StringBuilder(); if (isTrue) { return Method1(); } else { return Method2(); } }
如今进行了方法拆分,这两个方法就能够根据须要进行 JIT 编译,而没必要第一次进行所有编译。
2.能够将 if-else 分支中有超过几十条的语句,或者某个分支专门用来处理程序发生的错误,或者 switch 语句中的每一个 case 中的代码进行选择性的提取。
3.短小精悍的方法(通常包含较少的局部变量)会让 JIT 更容易地进行寄存器选择工做,即选择哪些局部变量放在寄存器中,而不是栈上。
4.尽可能编写短小精悍的方法。
《Effective C#》快速笔记(一)- C# 语言习惯
《Effective C#》快速笔记(二)- .NET 资源托管
《Effective C#》快速笔记(三)- 使用 C# 表达设计
《Effective C#》快速笔记(五) - C# 中的动态编程
《Effective C#》快速笔记(六) - C# 高效编程要点补充
【博主】反骨仔
【原文】http://www.cnblogs.com/liqingwen/p/6754401.html
【参考】《Effective C#》