C# 编程指南

前不久在 Github 上看见了一位大牛创建一个仓库:CSharpCodingGuidelines,打开之后看了一下 readme.md 相关描述,感觉应该很不错,于是就 clone 到本地拜读一下,这里列一些自己的笔记,方便日后回顾。

基本原则

  • Astonishment 原则:你的代码应该尽量做到让每一个人都能理解。任何人都有写出让机器认识的代码,但是并不是每个人都能写出让人认识的代码;
  • Kiss 原则:类似 Python 之禅 里面说的那样,简单胜于复杂;
  • YAGNI 原则:代码尽量能做到可扩展,但请不要过度重构,因为你不能预知未来;
  • DRY 原则:不要重复造轮子,除非你有时间或者你造的轮子会比别人的优秀;
  • 面向对象编程原则:继承、封装、多态、抽象;

类设计指南

  • 一个类/接口应该只有一个用途,要符 合单一职责 原则;
  • 只创建返回有用对象的构造函数,当构造函数的参数超过 3 的话,你就应该考虑你的类设计是否过于臃肿;
  • 接口应该短小精悍,其定义要明确清晰地传达出其具有的行为;
  • 如果一种行为有多种实现,请考虑使用接口而不是基类;
  • 尽量使用接口将类进行彼此解耦;
  • 避免使用静态类;
  • 不要使用 new 关键字来禁止编译器显示相关警告;
public class Book
{
public virtual void Print()
{
Console.WriteLine("Printing Book");
}
} public class PocketBook : Book
{
public new void Print()
{
Console.WriteLine("Printing PocketBook");
}
} class Program
{
static void Main(string[] args)
{
PocketBook pocketBook = new PocketBook();
pocketBook.Print(); ((Book)pocketBook).Print(); Console.ReadKey();
}
}

在上述代码段中,我们创建一个基类 book,并定义了一个 Print() 方法,接着我们创建一个子类 PocketBook,并通过 new 关键字来重写基类方法。在项目复杂的情况下,使用这种方式将导致我们不能准确预测是子类调用还是父类调用,使代码复杂度提升。

  • 应该可以将派生类当作基类对象来处理;
  • 不要引用基类的派生类;
  • 避免暴露一个对象依赖的其它对象;
  • 避免双向依赖;
  • 类应该有状态和行为;
  • 类应该保护其内部状态的一致性;

属性成员设计指南

  • 允许按任意顺序设置属性;
  • 使用方法而不是属性;
  • 不要使用相互排斥的属性;
  • 属性、方法或者本地方法只应该做一件事情;
  • 不要通过静态成员公开有状态的对象;
  • 用 IEnumerable 或者 ICollection 来代替具体的集合对象作为返回值;
  • 如果属性、参数和返回值是字符串或者集合类型的话,则永远不应该为空;
  • 尽可能地定义具体的参数;
  • 考虑使用特定域的值类型而不是基元;

其他设计指南

  • 抛出异常而不是返回某种类型的状态值;
  • 提供完整而有意义的异常信息;
  • 抛出适当的最具体的异常;
  • 不要通过 try - catch 方式隐藏异常;
  • 正确处理异步代码中的异常;
  • 调用事件委托前先判断是否为空;
event EventHandler<string> Notify;
protected virtual void OnNotify(string args)
{
Notify?.Invoke(this, args);
}
  • 使用受保护的虚方法来触发每个事件;
  • 考虑添加属性变化事件;
  • 当触发事件时要确保 sender != nulll;
  • 如果合适的话,请考虑使用泛型约束;
class SomeClass
{
} /// <summary>
/// 不推荐
/// </summary>
class MyClass1
{
void SomeMethod<T>(T t)
{
object temp = t;
SomeClass obj = (SomeClass)temp;
}
} /// <summary>
/// 推荐
/// </summary>
class MyClass2
{
void SomeMethod<T>(T t) where T :SomeClass
{
SomeClass obj = t;
}
}
  • 在返回 LINQ 表达式之前计算它的结果;
  • 如果不是必须,不要使用 thisbase 关键字;

可维护性指南

  • 方法内部的代码段尽量不要超过 7 行;
  • 确保所有成员私有,类的类型默认为为 internal sealed
  • 避免双重条件;
  • 在其包含的命名空间内命名程序集;
  • 将源文件命名为它所包含的类型;
  • 将源文件的内容限制为一种类型;
  • 将不同的逻辑函数放到同一个部分类中;
  • 在使用一个类型时,使用 using 关键字导入需要的命名空间,而不是类型的完整空间标识;
  • 不要使用魔法数;
  • 只有当类型显而易见时才使用 var 关键字;
  • 定义变量时尽可能地初始化;
  • 在相互独立的代码段中定义临时变量;
  • 若对象有集合需要初始化的话在进行对象初始化的同时进行集合初始化;
  • 不要显式进行 bool 值的比较;
  • 避免嵌套循环;
  • 在使用 ifelsedowhileforforeachcase 的同时使用 {}
  • switch case 代码段中添加 default 逻辑;
  • 在所有的 ifelse if 后再添加 else;
  • 避免使用多个返回值;
  • 考虑使用简单的条件语句代替 if else
  • 封装属性、方法或局部函数中的复杂表达式;
  • 再合适的情况下尝试重载方法;
  • 使用可选参数来代替重载;
  • 避免使用命名参数;
  • 避免定义超过3个参数的签名;
  • 避免函数签名为布尔类型;
  • 不要将参数作为临时变量使用;
  • 将模式作为操作;
  • 不要注释代码;

命名指南

  • 不要在变量、参数和类型成员中包含数字;
  • 不要在字段添加前缀;
  • 不要使用缩写;
  • 成员、参数和变量定义要根据它们代表的意义;
  • 使用名词、名词短语或者形容词来定义类型;
  • 使用描述性名称命名泛型参数;
  • 在类成员中不要重复定义和类相同的名称;
  • 成员定义可参考 .Net Framework 的定义方式;
  • 避免使用可能被误解的段名称或字段;
  • 正确定义属性;
  • 在命名方法或局部函数时使用谓词或谓词对象;
  • 使用名称、层、谓词和功能申明命名空间;
  • 使用动词或动词前缀来定义事件;
  • 使用 ingend 后缀来表达事件预处理和发送事件;
  • 使用 on 前缀来定义事件处理程序;
  • 使用 Async 或者 TaskAsync 来标识异步方法;

性能指南

  • 使用 Any() 判断 IEnumerable 是否为空 ;
  • 仅对低密集型活动使用异步;
  • 对于 CPU密集型使用 Task.Run
  • 避免同时将 async/awaitTask.Wait 混合使用;
  • 避免 async/await 在单线程环境下出现死锁;

框架指南

  • 使用 C# 类型 别名而不是系量进行显式调用;
  • 不要硬编码;统命名空间中的类型;
  • 使用最高警告级别编译代码;
  • 对于简单的表达式避免使用 LINQ
  • 使用 lambda 表达式来代替匿名函数;
  • 只用在使用动态对象时才使用 dynamic 关键字;
  • 支持异步/等待任务延续;

文档指南

  • 使用美式英语来编写相关文档;
  • 文档中的代码部分要保证完整性;
  • 与其他开发人员一起编写 xml 文档;
  • 编写 MSDN 风格的技术文档;
  • 避免内联注释;
  • 注释值应该用来解释复杂的算法或讨论;
  • 不要使用注释来跟踪要在以后完成的工作;

布局指南

  • 使用常规布局;
  • 根据公式要求进行命名空间的约束;
  • 将成员置于定义良好的顺序中;
  • 谨慎使用 #region
  • 适当使用表现健全的成员;

相关链接

读 《CSharp Coding Guidelines》有感的更多相关文章

  1. 读javascript高级程序设计00-目录

    javascript高级编程读书笔记系列,也是本砖头书.感觉js是一种很好上手的语言,不过本书细细读来发现了很多之前不了解的细节,受益良多.<br/>本笔记是为了方便日后查阅,仅作学习交流 ...

  2. 读javascript高级程序设计-目录

    javascript高级编程读书笔记系列,也是本砖头书.感觉js是一种很好上手的语言,不过本书细细读来发现了很多之前不了解的细节,受益良多.<br/>本笔记是为了方便日后查阅,仅作学习交流 ...

  3. JavaScript: The Evil Parts - 1

    最近在看JavaScript框架设计,在讲解类型判定的时候提到了一些“匪夷所思的情况”,不过没有明说都是什么时候会出现这些情况.自己玩儿了一下,写写随笔吧.不过可能除了我找到的,还有会其他时候会出现这 ...

  4. 读 《JavaScript: The Good Parts》 有感

    提炼出一门语言或技术的 Good Parts, 使用该子集去构造健壮稳固的应用. 我们总是倾向于去学习和使用所有的语言特性,好像凡是新的,凡是提供了的, 就有必要去使用: 这本书告诉我们, 要有选择性 ...

  5. 读javascript高级程序设计17-在线检测,cookie,子cookie

    一.在线状态检测 开发离线应用时,往往在离线状态时把数据存在本地,而在联机状态时再把数据发送到服务器.html5提供了检测在线状态的方法:navigator.onLine和online/offline ...

  6. JavaScript: The Good Parts

    Chapter 1 Good Parts: JavaScript is an important language because it is the language of the web brow ...

  7. 读javascript高级程序设计01-基本概念、数据类型、函数

    一. javascript构成 1.javascript实现由三部分组成: ECMAScript:核心语言功能 DOM:文档对象模型,提供访问和操作网页内容的方法和接口 BOM:浏览器对象模型,提供与 ...

  8. 读javascript高级程序设计02-变量作用域

    一. 延长作用域链 有些语句可以在作用域前端临时增加一个变量对象,该变量对象在代码执行完成后会被移除. ①with语句延长作用域. function buildUrl(){ var qs=" ...

  9. 读javascript高级程序设计08-引用类型之Global、Math、String

    一.Global 所有在全局作用域定义的属性和方法,都属于Global对象. 1.URI编码: encodeURI():主要用于对整个URI编码.它不会对本身属于URI的特殊字符进行编码. encod ...

  10. 读javascript高级程序设计10-DOM

    一.节点关系 元素的childNodes属性来表示其所有子节点,它是一个NodeList对象,会随着DOM结构的变化动态变化. hasChildNodes():是否有子节点. var headline ...

随机推荐

  1. nginx反向代理mysql及负载

    下载地址: http://nginx.org/packages/mainline/centos/7/x86_64/RPMS/nginx-1.15.9-1.el7_4.ngx.x86_64.rpm 安装 ...

  2. 为什么需要micro-service构建平台

    最近一直在做micro-service的开发平台建设.由于这是一个实验项目,目前所有工作都得靠自己操刀. 今天在总结用python开发一个web service时,偶有所得,这让我建设micro-se ...

  3. SQL Server表分区(水平分区及垂直分区)

    什么是表分区? 表分区分为水平表分区和垂直表分区,水平表分区就是将一个具有大量数据的表,进行拆分为具有相同表结构的若干个表:而垂直表分区就是把一个拥有多个字段的表,根据需要进行拆分列,然后根据某一个字 ...

  4. c++ 日志输出库 spdlog 简介(1)

    参考文章: log库spdlog简介及使用 - 网络资源是无限的 - CSDN博客 http://blog.csdn.net/fengbingchun/article/details/78347105 ...

  5. blender 快捷键手动整理

    armature envelop 设置骨骼影响范围:Edit Mode 下,选中骨头的其中一端,按 Alt + s,缩放 T 呼出 Tools N 呼出 Property Ctrl + Alt + Q ...

  6. React.js 三周 -- 入门到搭建团队基础项目

    吐槽 公司自己的产品,由于历史遗留问题,前端一直是和java放到一个项目里写的. 导致了,前端就被死死的绑在了IDEA战车上.想要看页面效果,先起几个java服务.想要调试一个改动,重启个java服务 ...

  7. Jmeter HTTP请求后响应数据显示乱码解决方法

    Jmeter请求后结果树里无论是text还是html响应数据显示乱码,这是因为jmeter 编码格式配置文件默认不开启导致的,解决方法如下: 1)进入jmeter-***\bin目录下,找到jmete ...

  8. Maven - Tips

    1- Maven的Settings http://maven.apache.org/settings.html 2- Maven设置代理 示例: <proxies> <proxy&g ...

  9. 12-部署EFK插件

    配置和安装 EFK 官方文件目录:cluster/addons/fluentd-elasticsearch $ ls *.yaml es-controller.yaml es-service.yaml ...

  10. laravel5.5 __construct函数 无法使用session() 解决方法和实例

    从网上查询资料得知,在laravel中使用__construct方法的时候,session还没开启,此时就需要用到中间件来解决. $this->middleware(function ($req ...