熱點推薦:
您现在的位置: 電腦知識網 >> 編程 >> ASP編程 >> 正文

C#幾個經常犯錯誤匯總

2022-06-13   來源: ASP編程 


    在我們平常編程中時間久了有時候會形成一種習慣性的思維方式形成固有的編程風格但是有些地方是需要斟酌的即使是一個很小的錯誤也可能會導致昂貴的代價要學會善於總結從錯誤中汲取教訓盡量不再犯同樣錯誤注重編程之美代碼的優雅總結幾個平常經常犯的錯誤
    在C#編程中字符型類型是最容易處理出錯的地方代價是非常昂貴Net Framwork中字符串是一個相當特別的引用類型string本省就是一個不可繼承的密封類但是它具有了值類型所應用的特點但是它在CLR中內存還是保存於托管堆之上也就是說當我們每次定義一個字符串類型的時候就在堆內存中開辟一端內存而當我們字符串被修改之後它會創建一個新的內存注意這裡的內存是不連續的而是通過修改棧內地址引用而拼湊字符串不會改變源字符串在內存中的地址所以有些程序員總是喜歡使用這樣的方法格式化字符串
    string  SelectText=select * from +TableName+ where UserName=+Name+;
    上述代碼使用了字符串拼湊的方法因為使用了多重串聯因此會在內存中創建兩個不必要的字符串垃圾副本
    其實在C#中已經為我們提供了StringBuilder和StringFromat來解決此問題雖然他們可以實現同樣的功能但是他們有質的變化StringBuilder在內存中開辟的是一段連續內存當增加新字符串時候它會在棧中指向的同一個堆內存中連續存放字符這就形成了性能的提升所以我們將上面代碼改成
    string SelectText=stringFormat(select  *  from {} where UserName={}TableNameName)
    大多數開發人員都不知道內置的驗證數據類型的方法如SystemInt因此很多人都是自己實現的其實這是不妥的因為這些基本類型中都存在自己固有的類型驗證方法下面這個就是自己實現驗證的一個字符串是否是數值的代碼

  


    public bool CheckIfNumeric(string value)  
    {  
        bool IsNumeric=true;  
        try 
         {  
               int i=ConvertToInt(value);  
         }  
         catch(FormatException excepiton)  
         {  
               IsNumeric=false;  
         }  
         return IsNumeric;  

  雖然使用了try catch語句這不是最佳的做法更好的方法是下面使用IntTryParse

  


    int output=;  
    bool IsNumeric=intTryParse(valueout output); 

  intTryParse是更快更簡潔的方法

  自己利用IDisposable接口手動釋放內存

  在NET Framework中對象的處理和使用一樣重要理想的方法是在使用完對象的時候在類中實現IDisposable接口中的dispose方法進行內存的釋放當然在Net本身提供的垃圾回收機制(GC)中就提供了這樣的功能在我們實例化類對象時在類本身的析構函數中會調用dispose方法GC在各級內存堆滿的情況下自動檢查對象使用情況去相應的釋放內存但是運行在非托管平台上的方法需要我們自己手動釋放內存比如我們常見的SqlConnection對象也就有了下面的創建使用和處理方法

  


    public void  DALOneMethod()  
    {  
        SqlConnection  connection=null;  
        try 
         {  
              connection =new SqlConnection();  
              connectionOpen();  
              //sqlcommandrun  
     
         }  
         catch(Exception exception)  
         {  
                 // manager exception  
         }  
         finally 
         {  
                connectionClose();  
                connectionDisopse();  
         }  

  上述代碼是大部分程序員會出現的代碼乍看沒啥問題連接處理在最後一個代碼中被明確調用但是如果發生了一個異常catch代碼塊就被執行然後再執行最後一個代碼塊處理連接因此在最後一個代碼塊執行之前連接將一直留在內存中大部分我們會在此處記錄錯誤一般涉及到IO操作如果延時時間比較長的話這個連接將在內存時間長時間停留我們一個原則就是當對象不再使用的時候我們裡面釋放資源

  我們采用程序邏輯域來處理這個問題會更好

  


    public void  DALOneMethod()  
    {  
        using(SqlConnction  connection=new SqlConnection())  
         {  
             connctionOpen()  
          // do SUAD  
         }  

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

  學會合理的管理公共變量我們在系統中經常會濫用公共變量沒有做到合適的封裝好

  


    static  void Main(string[]  args)  
    {  
                MyAccount  account=new MyAccount();  
               //這地方不能隨便的調用account裡面的字段進行更改但是缺改了  
            accountAccountNumber=ddddddddd;  
               ConsoleReadKey();  
    }  
    public class MyAccount  
    {  
              public  string AccountNumber;  
              public  MyAcctount()  
              {  
                    AccountNumber=ssssssssssssss;  
              }  

  在上面的MyAccount類中生命了一個AccountNumber公共變量理想情況下AccountNumber應該是只讀的不能讓外界修改但是這裡MyAccount類卻沒有對它做任何控制

  聲明公共做法應該是使用屬性

  


    public  class  MyAccount  
    {  
       private stirng _accountNumber;  
       public  string AccountNumber  
       {  
            get {  return  _accountNumber;  }  
       }  
       public  MyAccount()  
       {  
              _accountNumber=dddddddd;  
       }  

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

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

  


    public class NestedExceptionHandling  
      {  
          public void MainMethod()  
          {  
              try 
              {  
                  //some implementation  
                  ChildMethod();  
              }  
              catch (Exception exception)  
              {  
                  //Handle exception  
              }  
          }  
        
          private void ChildMethod()  
          {  
              try 
              {  
                  //some implementation  
                  ChildMethod();  
              }  
              catch (Exception exception)  
              {  
                  //Handle exception  
               throw;  
        
              }  
          }  
        
          private void ChildMethod()  
          {  
              try 
              {  
                  //some implementation  
              }  
              catch (Exception exception)  
              {  
                  //Handle exception  
                  throw;  
              }  
          }  
      } 

  如果相同的異常被處理多次性能開銷將會增加

  我們的解決方法是讓異常處理方法獨立開來

  


    public class NestedExceptionHandling  
      {  
          public void MainMethod()  
          {  
              try 
              {  
                  //some implementation  
                  ChildMethod();  
              }  
              catch(Exception exception)  
              {  
                  //Handle exception  
              }  
          }  
        
          private void ChildMethod()  
          {  
              //some implementation  
              ChildMethod();  
          }  
        
          private void ChildMethod()  
          {  
              //some implementation  
          }  
      } 

  大數據量上使用Dataset和DataReader混用當單表數據量很大的情況使用DataSet是一種很不明智的選擇應為DataSet是以DataTable內存形式存放數據量一次性將數據拖入內存當數據很大的情況下這種方式是很吃內存的相比DataSerDataReader就顯得優雅很多它是每次讀取一條數據然後輪詢調用機制但是也有它的弊端就是相對長連接但是對內存消耗而言這是有利的當然DataSet在大部分應用場景下也是有自己的優點充分解耦一次性操作領域模型操作等方面兩者分情況分場景而用這裡只是稍微提提根據場景分析區別


From:http://tw.wingwit.com/Article/program/ASP/201311/21846.html
    推薦文章
    Copyright © 2005-2022 電腦知識網 Computer Knowledge   All rights reserved.