文章目录
C#概述
C#语法基础
标识符
- 要更注重标识符的清晰而不是简短。
- 不要在标识符名称中使用单词缩写。
- 不要使用不被广泛接受的首字母缩写词,即使被广泛接受,非必要也不要用。
- 要把两个字母的首字母缩写词全部大写,除非它是camelCase标识符的第一个单词。
- 包含三个或更多字母的首字母缩写词,仅第一个字母才要大写, 除非该缩写词是camelCase标识符的第一个单词
- 在camelCase标识符开头的首字母缩写词中,所有字母都不要大写。
- 不要使用匈牙利命名法(不要为变量名称附加类型前缀)。
类型定义
-
要用名词或名词短语命名类。
-
要为所有类名使用PascalCase大小写风格。
使用变量
变量的声明
- 要为局部变量使用camelCase风格命名。
注释
- 不要使用注释,除非代码本身“一言难尽”。
- 要尽量写清楚的代码而不是通过注释澄清复杂的算法。
数据类型
基本数值类型
整数类型
- 要在指定数据类型时使用C#关键字而不是BCL名称(例如,使用string而不是String)。
- 要一致而不要变来变去。
字面值
- 要使用大写的字面值后缀(例如1.618033988749895M)
更多基本类型
字符串
- 要依赖 System.WriteLine() 和 System.Environment.NewLine 而不是 \n 来确保跨平台兼容。
更多数据类型
可空修饰符
隐式类型的局部变量
- 避免使用隐式类型的局部变量,除非所赋的值的数据类型显而易见。
元组
- 要为元组语法的变量声明使用camelCase大小写规范。
- 考虑为所有元组项名称使用PascalCase大小写风格。
操作符和控制流程
操作符
二元算术操作符(+,-,*,/,%)
- 要用圆括号增加代码的易读性,尤其是在操作符优先级不是让人一目了然的时候。
- 要在字符串可能会本地化时用复合格式化而不是加法操作符来连接字符串。
- 避免在需要准确的十进制小数算术运算时使用二进制浮点类型,改为使用decimal浮点类型。
- 避免将二进制浮点类型用于相等性条件式。要么判断两个值之差是否在容差范围之内,要么使用decimal类型。
递增和递减操作符(++,–)
- 避免递增和递减操作符的使用让人迷惑。
- 在C、C++和C#之间移植使用了递增和递减操作符的代码要小心;C和C++的实现遵循的不一定是和C#相同的规则。
常量表达式和常量符号
- 不要用常量表示将来可能改变的任何值。π和金原子的质子数是常量。金价、公司名和程序版本号则应该是变量。
代码块
- 除非最简单的单行if语句,否则避免省略大括号
布尔表达式
条件操作符(?:)
- 考虑使用if/else语句而不是过于复杂的条件表达式。
控制流程语句(续)
for循环
- 如果被迫要写包含复杂条件和多个循环变量的for循环,考虑重构方法使控制流程更容易理解。
- 事先知道循环次数,且循环中要用到控制循环次数的“计数器”,要使用for循环。
- 事先不知道循环次数而且不需要计数器,要使用while循环。
基本switch语句
- 不要使用continue作为跳转语句退出switch小节。如switch在循环中,这样写合法。但很容易对之后的switch小节中出现的break产生困惑。
跳转语句
goto语句
- 避免使用goto
方法和参数
方法的调用
- 要为方法名使用动词或动词短语。
命名空间
- 要为命名空间使用PascalCase大小写。
- 考虑组织源代码文件目录结构以匹配命名空间层次结构。
方法的声明
参数声明
- 要为参数名使用camelCase大小写。
高级方法参数
参数数组(params)
- 方法能处理任何数量(包括零个)额外实参时要使用参数数组。
可选参数
- 要尽量为所有参数提供好的默认值。
- 要提供简单的方法重载,必须的参数的数量要少。
- 考虑从最简单到最复杂组织重载。
- 要将参数名视为API的一部分;要强调API之间的版本兼容性,就避免改变名称。
用异常实现基本的错误处理
捕捉错误
- 避免从finally块显式抛出异常(因方法调用而隐式抛出的异常可以接受)。
- 要优先使用try/finally而不是try/catch块来实现资源清理代码。
- 要在抛出的异常中描述异常为什么发生。顺带说明如何防范更佳。
- 避免使用常规catch块,用捕捉System.Exception的catch块代替。
- 避免捕捉无法从中完全恢复的异常。这种异常未处理比不正确处理好。
- 避免在重新抛出前捕捉和记录异常。要允许异常逃脱(传播),直至它被正确处理。
使用throw语句报告错误
- 要在捕捉并重新抛出异常时使用空的throw语句,以便保留调用栈。
- 要通过抛出异常而不是返回错误码来报告执行失败。
- 不要让公共成员将异常作为返回值或者out参数。抛出异常来指明错误;不要把它们作为返回值来指明错误。
- 不要用异常处理正常的、预期的情况;用它们处理异常的、非预期的情况。
类
类的声明和实例化
- 不要在一个源代码文件中放多个类。
- 要用所含公共类型的名称命名源代码文件。
属性
属性和字段的设计规范
-
要使用属性简化对简单数据的访问(只进行简单计算)。
-
避免从属性取值方法抛出异常。
-
要在属性抛出异常时保留原始属性值。
-
如果不需要额外逻辑,要优先使用自动实现的属性,而不是属性加简单支持字段。
-
考虑为支持字段和属性使用相同的大小写风格,为支持字段附加“_”前缀。但不要使用双下划线,它是为 C# 编译器保留的。
-
要使用名词、名词短语或形容词命名属性。
-
考虑让某个属性和它的类型同名。
-
避免用 camelCase 大小写风格命名字段。
-
如果有意义的话,要为 Boolean 属性附加 ”Is“ “Can” 或 “Has” 前缀。
-
不要声明 public 或 protected 实例字段(而是通过属性公开)。
-
要用 PascalCase 大小写风格命名属性。
-
要优先使用自动实现的属性而不是字段。
-
如果没有额外的实现逻辑,要优先使用自动实现的属性而不是自己写完整版本。
提供属性验证
- 避免从属性外部(即使是从属性所在的类中)访问属性的支持字段。
- 创建 ArgumentException() 或 ArgumentNullException() 类型的异常时,要为 paramName 参数传递 “value” ,它是属性赋值方法隐含的参数名。
只读和只写属性
- 如属性值不变,要创建只读属性。
- 如属性值不变,从 C# 6.0 起要创建只读自动实现的属性而不是只读属性加支持字段。