C#幾個常常犯錯誤彙總

在咱們日常編程中,時間久了有時候會造成一種習慣性的思惟方式,造成固有的編程風格,可是有些地方是須要斟酌的,即便是一個很小的錯誤也可能會致使昂貴的代價,要學會善於總結,從錯誤中汲取教訓,儘可能再也不犯一樣錯誤,注重編程之美,代碼的優雅,總結幾個日常常常犯的錯誤。html

一、在C#編程中,字符型類型是最容易處理出錯的地方,代價是很是昂貴,在.Net Framwork中,字符串是一個至關特別的引用類型,string本省就是一個不可繼承的密封類,可是它具備了值類型所應用的特色,可是它在CLR中內 存仍是保存於託管堆之上,也就是說,當咱們每次定義一個字符串類型的時候,就在堆內存中開闢一端內存,而當咱們字符串被修改以後,它會建立一個新的內存, 注意這裏的內存是不連續的,而是經過修改棧內地址引用而拼湊字符串,不會改變源字符串在內存中的地址,因此有些程序員老是喜歡使用這樣的方法格式化字符 串:程序員

  1. string  SelectText="select * from "+TableName+" where UserName='"+Name+"'"

上述代碼,使用了字符串拼湊的方法,由於使用了多重串聯,所以會在內存中建立兩個沒必要要的字符串垃圾副本。sql

其實在C#中,已經爲咱們提供了StringBuilder和String.Fromat來解決此問題,雖然他們能夠實現一樣的功能,可是他們有質 的變化,StringBuilder在內存中開闢的是一段連續內存,當增長新字符串時候,它會在棧中指向的同一個堆內存中連續存放字符,這就造成了性能的 提高。因此咱們將上面代碼改爲:編程

  1. string SelectText=string.Format("select  *  from {0} where UserName={1}",TableName,Name); 

二、大多數開發人員都不知道內置的驗證數據類型的方法,如System.Int32,所以不少人都是本身實現的,其實這是不妥的,由於這些基本類型中都存在本身固有的類型驗證方法,下面這個就是本身實現驗證的一個字符串是不是數值的代碼:函數

  1. public bool CheckIfNumeric(string value)  
  2. {  
  3.     bool IsNumeric=true;  
  4.     try 
  5.      {  
  6.            int i=Convert.ToInt32(value);  
  7.      }  
  8.      catch(FormatException excepiton)  
  9.      {  
  10.            IsNumeric=false;  
  11.      }  
  12.      return IsNumeric;  

雖然使用了try catch語句,這不是最佳的作法,更好的方法是下面使用Int.TryParse;post

  1. int output=0;  
  2. bool IsNumeric=int.TryParse(value,out output); 

int.TryParse是更快、更簡潔的方法。性能

三、本身利用IDisposable接口手動釋放內存大數據

在.NET Framework中,對象的處理和使用同樣重要,理想的方法是在使用完對象的時候,在類中實現IDisposable接口中的dispose方法進行內 存的釋放,固然在.Net自己提供的垃圾回收機制(GC)中就提供了這樣的功能,在咱們實例化類對象時,在類自己的析構函數中會調用dispose方 法,GC在各級內存堆滿的狀況下,自動檢查對象使用狀況,去相應的釋放內存,可是運行在非託管平臺上的方法,須要咱們本身手動釋放內存,好比咱們常見的 SqlConnection對象,也就有了下面的建立、使用和處理方法:ui

  1. public void  DALOneMethod()  
  2. {  
  3.     SqlConnection  connection=null;  
  4.     try 
  5.      {  
  6.           connection =new SqlConnection("。。。。。。。。。。。");  
  7.           connection.Open();  
  8.           //sqlcommand。。run  
  9.  
  10.      }  
  11.      catch(Exception exception)  
  12.      {  
  13.              // manager exception  
  14.      }  
  15.      finally 
  16.      {  
  17.             connection.Close();  
  18.             connection.Disopse();  
  19.      }  

上述代碼是大部分程序員會出現的代碼,乍看沒啥問題,鏈接處理在最後一個代碼中被明確調用,可是若是發生了一個異常,catch代碼塊就被執行,然 後再執行最後一個代碼塊處理鏈接,所以在最後一個代碼塊執行以前,鏈接將一直留在內存中,大部分咱們會在此處記錄錯誤,通常涉及到IO操做,若是延時時間 比較長的話,這個鏈接將在內存時間長時間停留。咱們一個原則就是當對象再也不使用的時候咱們裏面釋放資源。spa

咱們採用程序邏輯域來處理這個問題會更好:

  1. public void  DALOneMethod()  
  2. {  
  3.     using(SqlConnction  connection=new SqlConnection("。。。。。。。"))  
  4.      {  
  5.          connction.Open();  
  6.       // do SUAD  
  7.      }  

當使用using代碼快時,對象上的dispose()方法將在執行推出邏輯域的時候調用,這樣就保證了SqlConnection的資源處理被盡 早釋放,固然這個方法也適用於實現IDisposable接口的類,當時我的不推薦這樣作,在很是有把握的狀況下能夠手動釋放,可是沒把握仍是叫 給.net系統釋放,由於自己類的析構函數就實現這個方法,當咱們本身重寫後,反而會致使系統誤覺得你本身定義了方法,而推遲釋放資源,有興趣能夠研究下 GC運行本質,假如能在第一代被釋放的內存,若是咱們重寫dispose方法反而推遲到第二代內存堆中釋放,顯然是不可取的。

四、學會合理的管理公共變量,咱們在系統中常常會濫用公共變量,沒有作到合適的封裝好。

  1. static  void Main(string[]  args)  
  2. {  
  3.             MyAccount  account=new MyAccount();  
  4.            //這地方不能隨便的調用account裏面的字段進行更改,可是缺改了  
  5.         account.AccountNumber="ddddddddd";  
  6.            Console.ReadKey();  
  7. }  
  8. public class MyAccount  
  9. {  
  10.           public  string AccountNumber;  
  11.           public  MyAcctount()  
  12.           {  
  13.                 AccountNumber="ssssssssssssss";  
  14.           }  

在上面的MyAccount類中生命了一個AccountNumber公共變量,理想狀況下,AccountNumber應該是隻讀的,不能讓外界修改,可是這裏MyAccount類卻沒有對它作任何控制。

聲明公共作法應該是使用屬性,如:

  1. public  class  MyAccount  
  2. {  
  3.    private stirng _accountNumber;  
  4.    public  string AccountNumber  
  5.    {  
  6.         get {  return  _accountNumber;  }  
  7.    }  
  8.    public  MyAccount()  
  9.    {  
  10.           _accountNumber="dddddddd";  
  11.    }  

這裏咱們封裝了AccountNumber公共變量,它變成了只讀,不能由調用者類進行修改。

五、嵌套的異常處理,有的開發人員喜歡在方法末尾加上處理的嵌套方法,如

  1. public class NestedExceptionHandling  
  2.   {  
  3.       public void MainMethod()  
  4.       {  
  5.           try 
  6.           {  
  7.               //some implementation  
  8.               ChildMethod1();  
  9.           }  
  10.           catch (Exception exception)  
  11.           {  
  12.               //Handle exception  
  13.           }  
  14.       }  
  15.     
  16.       private void ChildMethod1()  
  17.       {  
  18.           try 
  19.           {  
  20.               //some implementation  
  21.               ChildMethod2();  
  22.           }  
  23.           catch (Exception exception)  
  24.           {  
  25.               //Handle exception  
  26.            throw;  
  27.     
  28.           }  
  29.       }  
  30.     
  31.       private void ChildMethod2()  
  32.       {  
  33.           try 
  34.           {  
  35.               //some implementation  
  36.           }  
  37.           catch (Exception exception)  
  38.           {  
  39.               //Handle exception  
  40.               throw;  
  41.           }  
  42.       }  
  43.   } 

若是相同的異常被處理屢次,性能開銷將會增長。

咱們的解決方法是讓異常處理方法獨立開來,如:

  1. public class NestedExceptionHandling  
  2.   {  
  3.       public void MainMethod()  
  4.       {  
  5.           try 
  6.           {  
  7.               //some implementation  
  8.               ChildMethod1();  
  9.           }  
  10.           catch(Exception exception)  
  11.           {  
  12.               //Handle exception  
  13.           }  
  14.       }  
  15.     
  16.       private void ChildMethod1()  
  17.       {  
  18.           //some implementation  
  19.           ChildMethod2();  
  20.       }  
  21.     
  22.       private void ChildMethod2()  
  23.       {  
  24.           //some implementation  
  25.       }  
  26.   } 

六、大數據量上使用Dataset和DataReader混用,當單表數據量很大的狀況,使用DataSet是一種很不明智的選擇,應爲 DataSet是以DataTable內存形式存放數據量,一次性將數據拖入內存,當數據很大的狀況下,這種方式是很吃內存的,相比 DataSer,DataReader就顯得優雅不少,它是每次讀取一條數據,而後輪詢調用機制,可是也有它的弊端,就是相對長鏈接,可是對內存消耗而言 這是有利的,固然DataSet在大部分應用場景下也是有本身的優勢,充分解耦、一次性操做、領域模型操做等方面,二者分狀況分場景而用,這裏只是稍微提 提,根據場景分析區別。

原文連接:http://www.cnblogs.com/zhijianliutang/archive/2012/03/20/2407688.html

相關文章
相關標籤/搜索