这是一个大纲形式的概要,以便自己可以花较少的时间反复阅读。在开发中,多加注意这些有用的建议,让自己成为一个更优秀的程序员。内容主要来自《编写高质量代码-改善C#程序的157个建议》(陆敏技),这本书写的真的很好,都是些实战经验的总结,建议大家购买,这其中的建议不仅仅适合于C#,只要你做.NET开发,阅读此书都会从中受益。同时,其他书籍和资料的一些好的编程建议,我也会不断更新到这里。

1, 字符串使用。

应避免发生装箱;避免分配额外的内存;考虑使用StringBuilder来替代string。string.Format内部使用了StringBuilder,比较高效。

2, 类型转换。

主要这几方面,基元类型(int32,double,string,object等)之间的转换包括隐式转换和显示转化,自定义类型可以重载运算符实现隐式转换(implicit);类型本身提供了Prase和TryPrase,或ToDouble、ToDateTime等方法;帮助类如System.Convert实现基元类型之间的转换,System.BitConverter实现基元类型和数组之间的转换。父子类之间的显示和隐式转换。

3, As和Is。

尽量不要用Is判断后再强制转换的方式,直接用As运算符可以减少一次转型。

4, TryParse比Parse高效。

TryParse不会抛出异常,如果在循环中用Parse,频繁出现异常时会大大损害性能。

5, 使用int?确保值类型可以为null。

值类型可以隐式转换为可空值类型。判断可空类型是否包含值可以用HasValue方法测试,还可以用??运算符简化代码。

6, Readonly和const。

const是一个编译期常量,readonly是一个运行时常量。Const只能修饰基元类型、枚举类型和字符串类型;readonly可以修饰任何类型。Const天生就是static的,不用添加static修饰符。Readonly比const有更好的灵活性,但性能略有损失,比起这点性能损失,更推荐用readonly。

7, 将0值作为枚举类型的默认值。

枚举类型在声明时默认值是0,如果0值没有对应相应的枚举值将丧失业务意义。

8, 避免给枚举元素提供显示的值。

因为如何想在枚举的中间添加一个元素,不得不重新修改后面所有元素的值。这种情况有一个例外是应用了FlagAttribute的枚举,可以显示赋值。

9, 习惯重载运算符。

如果自己设计的类有加法意义,应该用operator关键字重载+运算符,使用户使用更加自然。

10, 创建对象时考虑是否实现比较器。

如果对象要用于排序,应该实现IComparable接口。如果想改变这种默认的排序策略,也可以自定义类实现ICompare接口,后者无需去改变类型的结构,而是添加一个新类来实现,更加灵活。

11, 区别对待==和Equals。

这两个运算符都可以被重载,但都应该保证这样的语义:对于值类型,如果类型的值相等,都应该返回true;对于引用类型,如果类型指向同一个对象,都应返回true。对于自定义的类型,如有必要,可以重写Equals方法保证值相等就返回true。但一般不重载==,使其保留引用相等性的判断。另外,要判断两个对象是否是同一个对象,可以用Object.ReferenceEquals方法。

12, 重写Equals时要重写GetHashCode。

这是因为一些基于散列值的集合,如Hashtable,Dictionary等,会用到Key的HashCode值来查找Value值。既然Equals的含义被重写了,那么HashCode也应该与其保持一致。

13, 为类型输出格式化字符串。

一种是让类型继承IFormatable接口,另一种是自定义格式化器,需要实现IFormatProvider和ICustomFormatter。后者的实现更加灵活。

14, 浅拷贝和深拷贝。

这两种拷贝都应继承ICloneable接口来实现。浅拷贝可以用this.MemberwiseClone方法。深拷贝可以用BinaryFormatter将对象序列化到MemoryStream后,再反序列化成对象。如果在一个类中要同时实现浅拷贝和深拷贝,可以添加DeepClone和ShadowClone两个方法加以区分。

15, 使用dynamic来简化反射的调用。

Dynamic是.net 4.0引入的一个新特性,编译器不会对dynamic类型的变量进行检查,我们可以在dynamic的变量上调用方法,检查属性值,而不必写繁琐的反射代码。Var关键字只是一个语法糖,编译器编译后会替换成具体的变量类型,而dynamic被编译后,会转换成object类型,对方法和属性等的调用C#内部本质还是用反射来做的,但这大大减轻了程序员的工作量。

使用dynamic来简化反射的调用。Dynamic是.net 4.0引入的一个新特性,编译器不会对dynamic类型的变量进行检查,我们可以在dynamic的变量上调用方法,检查属性值,而不必写繁琐的反射代码。Var关键字只是一个语法糖,编译器编译后会替换成具体的变量类型,而dynamic被编译后,会转换成object类型,对方法和属性等的调用C#内部本质还是用反射来做的,但这大大减轻了程序员的工作量。

【进阶修炼】——改善C#程序质量(1)的更多相关文章

  1. 【进阶修炼】——改善C#程序质量(10)

    158,不要写冗余注释. 注释应该写代码没有表达的东西. 代码能够自我描述就不要加注释. 159,废弃的注释应该尽早删除. 废弃的注释由于年代太久远,已经和现在的代码逻辑不匹配了,这样的注释只会误导人 ...

  2. 【进阶修炼】——改善C#程序质量(9)

    140,使用默认的访问修饰符. 如果不加访问修饰符,成员变量的默认是private的,类默认是internal的.为了明确访问的权限,我倒是建议都加上访问修饰符,这省不了多少代码. 141,不知道该不 ...

  3. 【进阶修炼】——改善C#程序质量(8)

    122,以<Company>.<Component>作为命名空间. 如Microsoft.Windows.Design.也可以用域名作为空间,如www.microsoft.co ...

  4. 【进阶修炼】——改善C#程序质量(7)

    113,声明变量时考虑最大值. Ushort的最大值是65535,用于不同的用途这个变量可能发生溢出,所以设计时应充分了解每个变量的最大值. 114,MD5不再安全. MD5多用于信息完整性的校验.R ...

  5. 【进阶修炼】——改善C#程序质量(6)

    90,不应为抽象类指定public的构造函数. 抽象类即使指定了public的构造函数,也是不能实例化的,编译通不过.抽象类的构造函数应该设定为protected,它的作用应该是初始化自己的成员,以及 ...

  6. 【进阶修炼】——改善C#程序质量(5)

    71, 区分异步和多线程的应用场景. 计算机的很多硬件,如硬盘,光驱,声卡,网卡都有DMA(Direct Memory Access)功能,它可以不占用cpu的资源,而异步的提出恰恰就是基于这个的.而 ...

  7. 【进阶修炼】——改善C#程序质量(4)

    46, 显示释放资源,需要实现IDisposable接口. 最好按照微软建议的Dispose模式实现.实现了IDisposable接口后,在Using代码块中,垃圾会得到自动清理. 47, 即使提供了 ...

  8. 【进阶修炼】——改善C#程序质量(3)

    32, 总是优先考虑泛型. 泛型代码有很好的重复利用性,和类型安全性. 33, 应尽量避免在泛型类中声明静态成员. 静态成员达不到共享的目的.List<int>和List<Strin ...

  9. 【进阶修炼】——改善C#程序质量(2)

    16, 元素可变的情况下应避免用数组. 数组是定长的集合,可以考虑用ArrayList或List<T>集合.ArrayList元素是object类型,有装箱的开销,性能较低.另外Array ...

随机推荐

  1. kafaka学习

    创建一个topic: [root@hdp1 bin]# ./kafka-topics. --replication-factor --partitions --topic justin Created ...

  2. ITOO高校云平台V3.1--项目总结(二)

    自身责任要明白 心态要明白 布置任务要有反馈 总结 今天下午.举办了一场ITOO高校云平台3.1总结大会,针对3.1开发的过程中统计上来的问题进行讨论. 通过讨论统计上来的问题,映射到自身,看看自己还 ...

  3. springboot + mybatis-pagehelper 参数查询不分页的bug。。。

    mmp,搞了很久 官方git上给出的配置是这样的: 这样做分页,如果仅仅支持一个查询,没问题,但是如果你带参数查询了,那就分页会出问题 把这行注释了即可 reasonable是指的让分页更加的合理化, ...

  4. redis-3.0.0_rc5的RPM包制定

    首先查看脚本: # cat /tmp/redis_before.sh #!/bin/bash if [ ! -d /apps/redis-3.0.0-rc5 ];then mkdir -p /apps ...

  5. HTML5学习笔记(二十六):JavaScript的错误处理

    错误相关的调试和处理在开发中是特别重要的一种技能. try-catch 我们来看下面的情况: // noneFunc 这个方法并不存在 window.noneFunc(); // js 报错后终止运行 ...

  6. 菜鸟学Java(十八)——异常

    每个学编程的人在编程的过程中都会遇到各种异常.那么当我们遇到异常的时候该怎么处理呢?针对不同的异常我们又该采取什么具体的处理方式呢?这些问题在我开始学编程的很长一段时间里我都不太清楚,还好随着不断的学 ...

  7. lua -- handler

    handler 将 Lua 对象及其方法包装为一个匿名函数. 格式: 函数 = handler(对象, 对象.方法) 在 quick-cocos2d-x 中,许多功能需要传入一个 Lua 函数做参数, ...

  8. 源码分析HotSpot GC过程(三):TenuredGeneration的GC过程

    老年代TenuredGeneration所使用的垃圾回收算法是标记-压缩-清理算法.在回收阶段,将标记对象越过堆的空闲区移动到堆的另一端,所有被移动的对象的引用也会被更新指向新的位置.看起来像是把杂陈 ...

  9. STL deque用法

    Deque 容器 deque容器是C++标准模版库(STL,Standard Template Library)中的部分内容.deque容器类与vector类似,支持随机访问和快速插入删除,它在容器中 ...

  10. MyBatis教程目录

    MyBatis教程目录 2017-10-18  摘自 YSOcean MyBatis教程目录: 1 mybatis 详解(一)------JDBC 2 mybatis 详解(二)------入门实例( ...