随笔分类 -  编写高质量代码改善C#程序的157个建议

摘要:建议75:警惕线程不会立即启动现代的大多数操作系统都不是一个实时的操作系统,Windows系统也是如此。所以,不能奢望我们的线程能够立即启动。Windows内部会实现特殊的算法以进行线程之间的调度,在某个具体的时刻,它会决定当前应该运行哪个线程。这反映到最底层就是某个线程分配到了一定的CPU时间,可 阅读全文
posted @ 2017-12-06 16:28 指间的徘徊 阅读(244) 评论(0) 推荐(0) 编辑
摘要:建议74:警惕线程的IsBackground在CLR中,线程分为前台线程和后台线程,即每个线程都有一个IsBackground属性。两者在表现形式上的唯一区别是:如果前台线程不退出,应用程序的进程就会一直存在,必须所有的前台线程全部退出,应用程序才算退出。而后台进程则没有这方面的限制,如果应用程序退 阅读全文
posted @ 2017-12-06 16:26 指间的徘徊 阅读(275) 评论(0) 推荐(0) 编辑
摘要:建议73:避免锁定不恰当的同步对象在C#中,让线程同步的另一种编码方式就是使用线程锁。线程锁的原理,就是锁住一个资源,使得应用程序在此刻只有一个线程访问该资源。通俗地讲,就是让多线程变成单线程。在C#中,可以将被锁定的资源理解成new出来的普通CLR对象。既然需要锁定的资源就是C#中的一个对象,我们 阅读全文
posted @ 2017-12-06 16:23 指间的徘徊 阅读(235) 评论(0) 推荐(0) 编辑
摘要:建议72:在线程同步中使用信号量所谓线程同步,就是多个线程在某个对象上执行等待(也可理解为锁定该对象),直到该对象被解除锁定。C#中对象的类型分为引用类型和值类型。CLR在这两种类型上的等待是不一样的。我们可以简单地理解为在CLR中,值类型是不能被锁定的,即不能在一个值类型对象上执行等待。而在引用类 阅读全文
posted @ 2017-12-06 16:20 指间的徘徊 阅读(310) 评论(0) 推荐(0) 编辑
摘要:建议71:区分异步和多线程应用场景初学者有时候会将异步和多线程混为一谈。如果对它们之间的区别不是很清楚,很容易写出下面这样的代码: 上面的代码模拟了在一个Winform窗体程序中,单击Button获取某个网页的内容并显示出来。可以预见,如果该网页的内容很多,或者当前的网络状况不太好,获取网页的过程会 阅读全文
posted @ 2017-12-06 15:43 指间的徘徊 阅读(336) 评论(0) 推荐(0) 编辑
摘要:建议70:避免在调用栈较低的位置记录异常 并不是所有的异常都要被记录到日志,一类情况是异常发生的场景需要被记录,还有一类就是未被捕获的异常。未被捕获的异常通常被视为一个Bug,所以,对于它的记录,应该被视为系统的一个重要组成部分。 最适合记录异常和报告的是应用程序的最上层,这通常是UI层。假设存在这 阅读全文
posted @ 2017-12-06 15:40 指间的徘徊 阅读(242) 评论(0) 推荐(0) 编辑
摘要:建议69:应使用finally避免资源泄漏 除非发生让应用程序中断的异常,否则finally总是会先于return执行。finally的这个语言特性决定了资源释放的最佳位置就是在finally块中;另外,资源释放会随着调用堆栈由下往上执行。下面的代码验证了这一点,先定义一个需要释放的类: 再来模拟一 阅读全文
posted @ 2017-12-06 15:34 指间的徘徊 阅读(247) 评论(0) 推荐(0) 编辑
摘要:建议68:从System.Exception或其他常见的基本异常中派生异常 微软建议:从System.Exception或其他常见基本异常之一派生异常。在Visual Studio中输入Exception,然后按快捷键Tab,VS会自动创建一个自定义异常类: 这是一个标准的自定义异常,它同时告诉你, 阅读全文
posted @ 2017-12-06 15:25 指间的徘徊 阅读(297) 评论(0) 推荐(0) 编辑
摘要:建议67:慎用自定义异常 除非有充分的理由,否则不要创建自定义异常。如果要对某类程序出错做特殊处理,那就自定义异常。需要自定义异常的理由如下: 1)方便测试。通过抛出一个自定义的异常类型实例,我们可以使捕获的代码精确的知道所发生的事情,并以符合的方式进行恢复。 2)逻辑包装。自定义异常可以包装多个其 阅读全文
posted @ 2017-12-06 15:23 指间的徘徊 阅读(255) 评论(0) 推荐(0) 编辑
摘要:建议66:正确捕获多线程中的异常 多线程的异常处理需要采用特殊的方式。一下这种方式会存在问题: 应用程序并不会在这里捕获线程的异常,而是会直接退出。从.NET2.0开始,任何线程上未处理的异常都会导致应用程序的退出(先会触发APPDomain的UnhandledException)。上面的代码中的t 阅读全文
posted @ 2017-12-06 15:22 指间的徘徊 阅读(352) 评论(0) 推荐(0) 编辑
摘要:建议65:总是处理未捕获的异常 处理为捕获的异常是每个应用程序具备的基本功能,C#在APPDomain提供了UnhandledException事件来接收未捕获到的异常的通知。常见的应用如下: 未捕获异常通常就是运行时期的Bug,我们可以在AppDomain.CurrentDomain.Unhand 阅读全文
posted @ 2017-12-06 15:13 指间的徘徊 阅读(269) 评论(0) 推荐(0) 编辑
摘要:建议64:为循环增加Tester-Doer模式而不是将try-catch置于循环内 如果需要在循环中引发异常,你需要特别注意,应为抛出异常是一个相当影响性能的过程。应该尽量在循环当中对异常发生的一些条件进行判断,然后根据条件进行处理。 做个测试: 输出为: 796 0 以上代码中,我们预见了代码肯能 阅读全文
posted @ 2017-12-06 15:12 指间的徘徊 阅读(234) 评论(0) 推荐(0) 编辑
摘要:建议63:避免“吃掉”异常 嵌套异常是很危险的行为,一不小心就就会将异常堆栈信息,也就是真正的Bug出处隐藏起来。这还不是最严重的,最严重的就是“吃掉”异常,即捕获,然后不向上层throw。 避免“吃掉”异常,并不是说不应该“吃掉”异常,而是这里有个重要原则:该异常可被预见,并且通常情况它不能算是一 阅读全文
posted @ 2017-12-06 15:01 指间的徘徊 阅读(274) 评论(0) 推荐(0) 编辑
摘要:建议62:避免嵌套异常 应该允许异常在调用堆栈上往上传,不要过多的使用catch,然后再throw。过多的使用catch会带来两个问题: 1)代码更多了。这看上去好像你根本不知道怎么处理异常,所以你总是不停地catch。 2)隐藏了堆栈信息,使你不知道真正发生异常的地方。 无故地嵌套是我们应该极力避 阅读全文
posted @ 2017-12-06 15:00 指间的徘徊 阅读(248) 评论(0) 推荐(0) 编辑
摘要:建议61:避免在finally内撰写无效代码 在阐述建议之前,需要先提出一个问题:是否存在一种打破try-finally执行顺序的情况,答案是:不存在(除非应用程序本身因为某些很少出现的特殊情况在try块中退出)。应该始终认为finally内的代码会在方法return之前执行,哪怕return在tr 阅读全文
posted @ 2017-12-06 14:53 指间的徘徊 阅读(371) 评论(1) 推荐(0) 编辑
摘要:建议60:重新引发异常时使用Inner Exception 当捕获了某个异常,将其包装或重新引发异常的时候,如果其中包含了Inner Exception,则有助于程序员分析内部信息,方便代码调试。 以一个分布式系统为例,在进行远程通信的时候,可能会发生的情况肯能会有: 1)网卡被禁用或者网线断开,此 阅读全文
posted @ 2017-12-06 14:51 指间的徘徊 阅读(421) 评论(0) 推荐(0) 编辑
摘要:建议59:不要在不恰当的场合下引发异常 常见的不易于引发异常的情况是对在可控范围内的输入和输出引发异常。 此方法起码有两个地方欠妥: 1)判读Age不能为负数。这是一个正常的业务逻辑,它不应该被处理为一个异常。 2)应采用Tester-Doer来验证输入。 应该添加一个Tester方法: 调用代码: 阅读全文
posted @ 2017-12-06 14:49 指间的徘徊 阅读(281) 评论(0) 推荐(0) 编辑
摘要:建议58:用抛出异常代替返回错误代码 CLR异常机制的优点: 正常控制流会被立即中止,无效值或状态不会在系统中继续传播。 提供了统一的处理错误的方法。 提供了在构造函数、操作符重载及属性中报告异常的遍历机制。 提供了异常堆栈,便于开发者定位异常发生的位置。 不应该将异常机制用于正常控制流中,异常的发 阅读全文
posted @ 2017-12-06 14:34 指间的徘徊 阅读(361) 评论(0) 推荐(0) 编辑
摘要:建议57:实现ISerializable的子类型应负责父类的序列化 我们将要实现的继承自ISerializable的类型Employee有一个父类Person,假设Person没有实现序列化,而现在子类Employee却需要满足序列化的场景。不过序列化器并没有默认处理Person类型对象,这些事情只 阅读全文
posted @ 2017-12-06 11:51 指间的徘徊 阅读(257) 评论(0) 推荐(0) 编辑
摘要:建议56:使用继承ISerializable接口更灵活地控制序列化过程 接口ISerializable的意义在于,如果特性Serializable,以及与其像配套的OnDeserializedAttribute、OnDeserializingAttribute、OnSerializedAttribu 阅读全文
posted @ 2017-12-06 11:50 指间的徘徊 阅读(1249) 评论(0) 推荐(1) 编辑