C#幾個經常犯錯誤

來源:互聯網
上載者:User

在我們平常編程中,時間久了有時候會形成一種習慣性的思維方式,形成固有的編程風格,但是有些地方是需要斟酌的,即使是一個很小的錯誤也可能會導致昂貴的代價,要學會善於總結,從錯誤中汲取教訓,盡量不再犯同樣錯誤,注重編程之美,代碼的優雅,總結幾個平常經常犯的錯誤。

1、在C#編程中,字元型類型是最容易處理出錯的地方,代價是非常昂貴,在.Net Framwork中,字串是一個相當特別的參考型別,string本省就是一個不可繼承的密封類,但是它具有了實值型別所應用的特點,但是它在CLR中記憶體還是儲存於託管堆之上,也就是說,當我們每次定義一個字串類型的時候,就在堆記憶體中開闢一端記憶體,而當我們字串被修改之後,它會建立一個新的記憶體,注意這裡的記憶體是不連續的,而是通過修改棧內地址引用而拼湊字串,不會改變源字串在記憶體中的地址,所以有些程式員總是喜歡使用這樣的方法格式化字串:

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

上述代碼,使用了字串拼湊的方法,因為使用了多重串聯,因此會在記憶體中建立兩個不必要的字串垃圾副本。

其實在C#中,已經為我們提供了StringBuilder和String.Fromat來解決此問題,雖然他們可以實現同樣的功能,但是他們有質的變化,StringBuilder在記憶體中開闢的是一段連續記憶體,當增加新字串時候,它會在棧中指向的同一個堆記憶體中連續存放字元,這就形成了效能的提升。所以我們將上面代碼改成:

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

2、大多數開發人員都不知道內建的驗證資料類型的方法,如System.Int32,因此很多人都是自己實現的,其實這是不妥的,因為這些基本類型中都存在自己固有的類型驗證方法,下面這個就是自己實現驗證的一個字串是否是數值的代碼:

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

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

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

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

3、自己利用IDisposable介面手動釋放記憶體

在.NET Framework中,對象的處理和使用一樣重要,理想的方法是在使用完對象的時候,在類中實現IDisposable介面中的dispose方法進行記憶體的釋放,當然在.Net本身提供的記憶體回收機制(GC)中就提供了這樣的功能,在我們執行個體化類對象時,在類本身的解構函式中會調用dispose方法,GC在各級記憶體堆滿的情況下,自動檢查對象使用方式,去相應的釋放記憶體,但是運行在非託管平台上的方法,需要我們自己手動釋放記憶體,比如我們常見的SqlConnection對象,也就有了下面的建立、使用和處理方法:

public void  DALOneMethod()
{
SqlConnection connection=null;
try
{
connection =new SqlConnection("。。。。。。。。。。。");
connection.Open();
//sqlcommand。。run

}
catch(Exception exception)
{
// manager exception
}
finally
{
connection.Close();
connection.Disopse();
}
}

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

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

public void  DALOneMethod()
{
using(SqlConnction connection=new SqlConnection("。。。。。。。"))
{
connction.Open();
// do SUAD
}
}

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

4、學會合理的管理公開變數,我們在系統中經常會濫用公開變數,沒有做到合適的封裝好。

static  void Main(string[]  args)
{
MyAccount account=new MyAccount();
//這地方不能隨便的調用account裡面的欄位變更,但是缺改了
account.AccountNumber="ddddddddd";
Console.ReadKey();
}
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公開變數,它變成了唯讀,不能由調用者類進行修改。

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

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

private void ChildMethod1()
{
try
{
//some implementation
ChildMethod2();
}
catch (Exception exception)
{
//Handle exception
throw;

}
}

private void ChildMethod2()
{
try
{
//some implementation
}
catch (Exception exception)
{
//Handle exception
throw;
}
}
}

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

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

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

private void ChildMethod1()
{
//some implementation
ChildMethod2();
}

private void ChildMethod2()
{
//some implementation
}
}

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

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.