1. string.Equals()
string.Equals方法有很多的重载供我们使用,但是其中有些常常会被我们忽视掉。通常我们比较字符串会使用下面的方法
public Order CreateOrder(string orderType, string product, int quantity, double price) { if (orderType.Equals("equity")) { } // ... }
如果orderType为null会抛出NullReferenceException异常,所以为了不抛出异常,在判断之前先要进行null的判断,如下:
if (orderType != null && orderType.Equals("equity"))
相当于每次都要做两次判断,很麻烦而且有时还有可能遗忘,如果使用string.Equals就可以解决这个问题,代码如下:
if (string.Equals(orderType, "equity"))
上面的代码当orderType为null时不会抛出异常而是直接返回false。
判断字符串相等的时候有时会需要区分大小写,很多人的习惯做法是先转换成大小或是小些在进行比较(建议转换成大写,因为编译器做了优化可以提高性能),但是当转换成大写或是小写时又会创建的的字符串,使性能降低。这时应该使用StringComparison.InvariantCultureIgnoreCase,代码如下
if (orderType.Equals("equity", StringComparison.InvariantCultureIgnoreCase))
如果要考虑到null的情况,还是应该使用string.Equal
if (string.Equals(orderType, "equity", StringComparison.InvariantCultureIgnoreCase))
2.Trim() 会产生一个新字符串
MSDN里写到: 此方法不修改当前实例的值。而是返回一个新字符串,在该字符串中,当前实例中找到的所有前导和尾随空白字符均被移除。
这样, 用它就会影响一些性能.
3.string.IsNullOrEmpty() and string.IsNullOrWhiteSpace()
在Net2.0中String类型有一个静态方法IsNullOrEmpty,到了Net4.0中String类又增加了一个新的静态方法IsNullOrWhiteSpace。这两个方法看名称也可以知道IsNullOrEmpty是判断空引用和空字符串,而IsNullOrWhiteSpace是判断空引用和字符串中的每一个字符是否是空格。
在有这两个方法之前,我们要进行这样的判断,需要些如下代码
public string GetFileName(string fullPathFileName) { if (fullPathFileName == null || fullPathFileName.Length == 0) { throw new ArgumentNullException(fullPathFileName); } //... }使用IsNullOrEmpty
public string GetFileName(string fullPathFileName) { if (string.IsNullOrEmpty(fullPathFileName)) { throw new ArgumentNullException(fullPathFileName); } //... }下面又了新的需求,需要将三个名字连接在一起,并且希望中间名字不为空字符串和不出现多余的空格,我们会写出下面的代码
public string GetFullName(string firstName, string middleName, string lastName) { if (middleName == null || middleName.Trim().Length == 0) { return string.Format("{0} {1}", firstName, lastName); } return string.Format("{0} {1} {2}", firstName, middleName, lastName); }上面的代码中使用了Trim来去掉空格然后判断其长度是否为0,代码也非常的清晰简洁,但是会产生额外的String对象以至于影响性能,这时就应该使用Net4.0中的IsNullOrWhiteSpace方法
public string GetFullName(string firstName, string middleName, string lastName) { if (string.IsNullOrWhiteSpace(middleName)) { return string.Format("{0} {1}", firstName, lastName); } return string.Format("{0} {1} {2}", firstName, middleName, lastName); }上面的代码非常简洁,而且也不用担心会产生额外的String对象没有及时的进行垃圾回收而影响性能。
4. using语句
我们都知道using最常用的地方就是在类中引用命名空间。除此之外还可以用作设置别名和应用在一些实现了IDisposable 借口的对象实例上,可以使这些对象在using的作用范围内自动释放资源。下面的代码示例是没有使用using的情况:
public IEnumerable<Order> GetOrders() { var orders = new List<Order>(); var con = new SqlConnection("some connection string"); var cmd = new SqlCommand("select * from orders", con); var rs = cmd.ExecuteReader(); while (rs.Read()) { // ... } rs.Dispose(); cmd.Dispose(); con.Dispose(); return orders; }上面的代码不怎么好看,而且也没有对异常的处理,如果在代码执行过程中出现了异常将会导致有些资源不能及时释放,尽管最终还是会被垃圾回收,但还是会影响性能呢。下面的代码添加了异常处理
public IEnumerable<Order> GetOrders() { SqlConnection con = null; SqlCommand cmd = null; SqlDataReader rs = null; var orders = new List<Order>(); try { con = new SqlConnection("some connection string"); cmd = new SqlCommand("select * from orders", con); rs = cmd.ExecuteReader(); while (rs.Read()) { // ... } } finally { rs.Dispose(); cmd.Dispose(); con.Dispose(); } return orders; }上面的代码仍然存在不足,如果SqlCommand对象创建失败或是抛出了异常,rs就会为null,那么最后在执行rs.Dispose()时就会抛出异常,会导致con.Dispose不能被调用,所以我们应该避免这种情况的发生
public IEnumerable<Order> GetOrders() { var orders = new List<Order>(); using (var con = new SqlConnection("some connection string")) { using (var cmd = new SqlCommand("select * from orders", con)) { using (var rs = cmd.ExecuteReader()) { while (rs.Read()) { // ... } } } } return orders; }上面的代码中的using嵌套了好几层,看起来很繁琐,而且可读性也不是很好,我们可以像下面这样改进
public IEnumerable<Order> GetOrders() { var orders = new List<Order>(); using (var con = new SqlConnection("some connection string")) using (var cmd = new SqlCommand("select * from orders", con)) using (var rs = cmd.ExecuteReader()) { while (rs.Read()) { // ... } } return orders; }