寫出優雅簡明代碼的論題集 -- Csharp(C#)篇[1]

作者: 擁有的都是恩典(宋歷)  來源: 博客園  發布時間: 2011-02-14 23:01  閱讀: 1419 次  推薦: 0   原文鏈接   [收藏]  

  最近和一些朋友討論如何寫出優雅的代碼,我們都很喜歡C#,所以以C#為例。主要一共有三位程序員在一起討論,為簡單起見我用ABC代表我們三個人。

  有時候我們會針對一些代碼進行討論,有時候我們會提出一些觀點,有時候我們會一起學習網上一些現有的博客,為了便于大家引用,我給每一個論題都編上號。

  在很多情況下,我們的意見統一,那么我會給大家呈現我們的結論;但是有些情況我們有分歧。

  你可以加入我們的討論,我非常也希望能夠獲知你的意見,讓我們一起茁壯成長!

  好吧,讓我們今天就開始。

  論題一:函數越小越好!

象鼠  相信絕大部分程序員會認同這一點,維護一個超過100行的函數會讓人抓狂。

  我記得我以前修改過一個用cobol寫的程序,一個文件超過10萬行,我為了進行一個極其小的修改花了3天的時間,而且最后自己也不知道會不會造成什么嚴重的后果。-- 這已經過去8年了,希望那段代碼運行良好。

  到底理想狀態下,我們的函數應該不大于多少行?我們三個人的答案是:

  A: 10 行

  B: 15 行

  C: 20 行

  論題二:用 Linq 簡化代碼

  Linq有時可以幫助我們寫出一些非常“人性”的語句。

  下面的這個函數是用于在數據庫中插入新的評論:

 
public static void Create(IEnumerable<CommentData> Comments, SqlConnection cn)
{

// validate params
if (null == cn) throw new ArgumentNullException("cn");
if (cn.State != ConnectionState.Open) throw new ArgumentException("Invalid parameter: connection is not open.", "cn");
if (null == Comments) throw new ArgumentNullException("Comments");
foreach (CommentData data in Comments)
{

if (data.CommentId.HasValue)
throw new ArgumentNullException("Create is only for saving new data. Call save for existing data.", "data");
}
...

  其中foreach這一部分可以簡化為:

 
if (Comments.Any(data => data.CommentId.HasValue))
{

throw new ArgumentNullException("Create is only for saving new data. Call save for existing data.", "data");
}

  在這一點上,我們存在分歧,A認為沒有必要進行簡化,因為原來的已經很明確了;但B認為簡化后的代碼可讀性更強,看上去更加直接。

   論題三:集合初始值

  希望每個人都已經知道C#的這個用法了,直接上一些代碼:

  3.1

  原始代碼:

 
List<int> idsToFind = new List<int>();
idsToFind.Add(
1);
idsToFind.Add(
2);

  修改后:

 
List<int> idsToFind = new List<int> {1, 2};

  3.2

  原始代碼:

 
var startingPoint = new Point();
startingPoint.X
= 5;
startingPoint.Y
= 13;

  修改后:

 
var startingPoint = new Point() { X = 5, Y = 13 };

  論題四:運用 ?:和??

  據說,有些公司會拿這個來測試入門的程序員:

  4.1

  原始代碼:

 
if (c != null)
System.Console.WriteLine(c.Name);

else
System.Console.WriteLine("List element has null value.");

  修改后:

 
System.Console.WriteLine(c != null ? c.Name : "List element has null value.");

  4.2

  原始代碼:

 
string name = value;
if (value == null)
{
name
= string.Empty;
}

  修改后:

 
string name = (value != null) ? value : string.Empty;

  還可以更簡單,變成:

 
string name = value ?? string.Empty;

  論題五: 運用AS

  原始代碼:

 
if (employee is SalariedEmployee)
{
var salEmp
= (SalariedEmployee)employee;
pay
= salEmp.WeeklySalary;
// ...
}

  修改后:

 
var salEmployee = employee as SalariedEmployee;
if (salEmployee != null)
{
pay
= salEmployee.WeeklySalary;
// ...
}

  論題六: 運用 using

  using首次出現是在visual studio 2005 中,在這以前,很多程序員暈倒在了釋放資源的邏輯中。使用using語句實際上生成的IL代碼中是一個try, finally代碼塊,在finally代碼塊里釋放資源。
  原始代碼:
 
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;
}

  這是一段非常丑陋的代碼,我們完全迷失在dispose群中,什么時候要調用哪個dispose啊? 天哪? 如果我們用 finally, 可以將代碼寫為:

 
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;
}

  看看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;
}
  好多了,對嗎? 完全不用再用那一堆的try/finally 代碼了,也不用使用一堆的null,為了使代碼更輕巧,讓我們再做小小修改:
 
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;
}

  未完待繼…

0
0
 
標簽:C#
 
 

文章列表

arrow
arrow
    全站熱搜
    創作者介紹
    創作者 大師兄 的頭像
    大師兄

    IT工程師數位筆記本

    大師兄 發表在 痞客邦 留言(0) 人氣()