C#程序编写高质量代码改善的157个建议【4-9】[TryParse比Parse、使用int?来确保值类型也可以为null、readonly和const、0值设为枚举的默认值、避免给枚举类型的元素提供显式的值、习惯重载运算符]
如果注意观察,除string之外的所有的基元类型。会发现它们都有两个将字符串转换为自身类型的方法:parse和tryparse。以类型double为例。
两者最大的区别是,如果字符串格式不满足转换的要求,parse方法将会引发一个异常;tryparse方法则不会引发异常,它会返回false,同时将result置为0。
//parse int a = int.parse("123a"); //tryparse int x = 0; if (int.tryparse("12a3", out x)) { //转换成功,x=123 } else { //转换失败,x=0 }
parse转换失败会运行时报错
而tryparse转换失败返回false,将其赋值为0
tryparse和parse两者都执行成功,那么tryparse的性能要比parse性能稍微好一点,但是如果抛出异常,那么tryparse的性能比parse提升了不少额。
不过这里并不建议为所有的类型都提供tryparse模式,只有在考虑到parse会带来明显的性能损耗时,才建议使用tryparse。
建议5、使用int?来确保值类型也可以为null
基元类型为什么需要为null?需要考虑以下两个场景:
1、数据库中一个int字段可以被设置为null。在c#中,值被取出来后,为了将它赋值给int类型,不得不首先判断一下它是否为null。如果将null直接赋值给int类型,会引发异常。
2、在一个分布式系统中,服务器需要接收并解析来自客户端的数据。一个int型数据在传输的过程中可能会丢失或者被篡改。转型失败后应该保存为null值,而不是提供一个默认值。
类似的场景还有很多,在这里不进行更详尽的列举。在.net2.0开始,便提供了一个额外的类型:可以为空的类型nullable<t>。
通过定义可以发现,它是一个结构体。因为是结构体,所以只有值类型才可以作为“可以为空的类型”(引用类型本身可以为null)。一个可以为空的int类型可以表示为
nullable<int> inta = null;
它也可以表示为
int? inta = null;
当然之后可以这样进行应用
int? i=123; int j = i ?? 0;
建议6、区别readonly和const的使用方法
关于两者的使用我之前也有专门介绍过,在这里就一笔带过:http://www.cnblogs.com/aehyok/p/3529079.html。
建议7、将0值设为枚举的默认值
允许使用的枚举类型有byte、sbyte、short、ushort、int、uint、long、ulong、应该始终将0值作为枚举的默认值。接下来我们通过示例来说明问题
enum week { money = 1, tuesday = 2, wednesday = 3, thursday = 4, friday = 5, saturday = 6, sunday = 7 }
在调用的时候发现
结果竟然出来了一个0,让人感觉怎么是第八个值出现了。所以建议将0设置为枚举的默认值。
建议8、避免给枚举类型的元素提供显式的值
一般情况下,没有必要给枚举类型的元素提供显式的值。创建枚举的理由之一,就是为了代替使用实际的值。不正确的为枚举类型的元素设定显式的值,会带来意想不到的错误。
enum week { money = 1, tuesday = 2, tempvalue, wednesday = 3, thursday = 4, friday = 5, saturday = 6, sunday = 7 }
假如我们在如上枚举中,又添加了一个tempvalue的元素。可以先猜测一下此时tempvalue的值会是多少?
通过调试可以发现。当编译器发现元素valuetemp的时候,它会自动在tuesday=2的基础上+1,所以valuetemp的值和wednesday的值都是3。可见,枚举元素允许设定重复的值。
注意: 本建议也有例外的情况。例如,当为一个枚举类型指定system.flagsattribute属性就意味着可以为这些值执行and、or、not、xor按位运算了,这样一来,枚举的每个元素的值就要求都是2的若干次幂,指数依次递增。
[flags] enum week { none = 0x0, money = 0x1, tuesday = 0x2, wednesday = 0x4, thursday = 0x8, friday = 0x10, saturday = 0x20, sunday = 0x40 }
按位运算在这里不多说了,详情可以查看 http://www.cnblogs.com/netbelieve/archive/2012/07/30/2615006.html
建议9、习惯重载运算符
在开发的过程中,应该习惯于使用微软提供给我们的语法特性。我想大部分人应该喜欢看到这样的语法特性:
int x = 7; int y = 8; int total = x + y;
而不是看到下面的语法:
int x = 7; int y = 8; int total = int.add(x, y);
所以我们在自定义类型的时候,也可以考虑看看类型是否可以使用运算符重载。
public class salary { public int rmb { get; set; } public static salary operator +(salary s1, salary s2) { s2.rmb += s1.rmb; return s2; } }
那现在我们来进行调用的时候就方便了很多。
salary s1 = new salary() { rmb = 10 }; salary s2 = new salary() { rmb = 20 }; salary s3 = s1 + s2;