1.使用as或is的優(yōu)勢(shì):
如果無法進(jìn)行轉(zhuǎn)換,則 null 而非引發(fā)異常,只需要檢查返回的引用是否為null即可,避免了異常處理帶來的開銷。
使用as操作符轉(zhuǎn)換對(duì)象為null時(shí)返回null,如果使用強(qiáng)制轉(zhuǎn)換的方式null可以被轉(zhuǎn)換成任意的引用類型。
as操作符的限制:
as操作符不能配合值類型使用,因?yàn)樗鼈冇肋h(yuǎn)都不可能為null。
is操作符的使用:
在不確定的強(qiáng)制類型轉(zhuǎn)換中使用異常來控制程序流是一個(gè)很糟糕的做法,在轉(zhuǎn)換之前我們可以使用is來避免冒出異常或轉(zhuǎn)換。
當(dāng)不能使用as進(jìn)行轉(zhuǎn)換時(shí),才應(yīng)該使用is操作符。否則is是多余的;因?yàn)槭褂胊s操作符只需要檢查是否為null即可,這樣更加簡(jiǎn)單。
2.使用Conditional特性:
[Conditional("DEBUG")]
private void CheckMethod(){}
Conditional特性的限制:
Conditional特性只可以應(yīng)用在整個(gè)方法上。
任何使用了Conditional特性的方法都只能返回void類型。
3.裝箱和取消裝箱
System.Collections.ArrayList.如果必須頻繁地將值類型裝箱,則最好避免使用值類型,例如在非泛型集合類 如 [System.Collections.ArrayList]可以通過使用泛型集合(例如 [System.Collections.Generic.List<T>]來避免將值類型裝箱。
裝箱和拆箱都是需要大量運(yùn)算的過程:
對(duì)值類型進(jìn)行裝箱時(shí),必須創(chuàng)建一個(gè)全新的對(duì)象。此操作所需時(shí)間可比簡(jiǎn)單的引用賦值操作長(zhǎng) 20 倍。
取消裝箱時(shí),強(qiáng)制轉(zhuǎn)換過程所需時(shí)間可達(dá)賦值操作的四倍。
4.在連接大量字符串變量時(shí),例如在緊湊循環(huán)中,請(qǐng)使用 [System.Text.StringBuilder] 而不是 C# [+ 運(yùn)算符]或 Visual Basic 串聯(lián)運(yùn)算符
注:string.format 方法,其實(shí)最終是調(diào)用 StringBuilder
public static string Format(IFormatProvider provider, string format, params object[] args)
{
if ((format == null) || (args == null))
{
throw new ArgumentNullException((format == null) ? "format" : "args");
}
StringBuilder builder = new StringBuilder(format.Length + (args.Length * 8));
builder.AppendFormat(provider, format, args);
return builder.ToString();
}
StringBuilder 是預(yù)先創(chuàng)建一個(gè)比較大的內(nèi)存,以后每次操作時(shí)判斷容量上限是否不夠用,如果不夠用就自動(dòng)把容量擴(kuò)大一倍,修改的還是第一次創(chuàng)建的對(duì)象的值。
結(jié)論:簡(jiǎn)單的拼接:用string.foramt
循環(huán)內(nèi)拼寫很長(zhǎng)的字符串時(shí),就需要用到StringBuilder來節(jié)省性能和內(nèi)存了。
5.析構(gòu)函數(shù)
不應(yīng)使用空析構(gòu)函數(shù)。如果類包含析構(gòu)函數(shù),F(xiàn)inalize 隊(duì)列中則會(huì)創(chuàng)建一個(gè)項(xiàng)。
調(diào)用析構(gòu)函數(shù)時(shí),將調(diào)用垃圾回收器來處理該隊(duì)列。 如果析構(gòu)函數(shù)為空,只會(huì)導(dǎo)致性能降低
6.使用using和try/finally清理資源
在C#中為我們添加了一個(gè)現(xiàn)實(shí)釋放非托管資源的關(guān)鍵字:using:
using語句其實(shí)是一個(gè)C#語言的語法糖,當(dāng)我們?cè)趗sing語句中分配可釋放對(duì)象時(shí),C#編譯器將會(huì)自動(dòng)在每個(gè)對(duì)象外生成一個(gè)try/finally塊來包裹住分配的對(duì)象,保證資源的及時(shí)釋放,即使拋出了異常也一樣。如果要使用一個(gè)可銷毀的對(duì)象,使用using語句能夠以最簡(jiǎn)單的方式保證你的對(duì)象可以正常銷毀。
注意:如果using語句中分配的變量的類型沒有實(shí)現(xiàn)IDisposable接口,編譯器將會(huì)拋出異常。
安全銷毀對(duì)象:
對(duì)于一些可能實(shí)現(xiàn)或未實(shí)現(xiàn)IDisposable接口的對(duì)象,或者無法確定是否應(yīng)該用using語句包裹某個(gè)對(duì)象時(shí),由于其不確定性我們可以使用as操作符進(jìn)行安全的銷毀
object obj = Factory.CreateResource();
//如果不確定obj是否實(shí)現(xiàn)了IDisposable接口,下面是安全的銷毀方式
using (obj as IDisposable)
{
Console.WriteLine(obj.ToString());
}
如果obj實(shí)現(xiàn)了IDisposable接口,那么using語句將生成清理代碼;反之,using語句將變成using(null) ,這并不會(huì)拋出異常,也不會(huì)有任何其他意料之外的操作。
必須保證每個(gè)實(shí)現(xiàn)了IDisposable接口的對(duì)象都放在了using或try/finally中,否則就可能會(huì)發(fā)生資源泄露。
釋放可銷毀對(duì)象的方式:
我們發(fā)現(xiàn)在我們釋放可銷毀對(duì)象時(shí)。有的類型不但提供Dispose()方法還提供了一個(gè)Close方法,比如前面示例中SqlConnection類的myConnection對(duì)象,我們可以知道調(diào)用myConnection對(duì)象的Close方法關(guān)閉數(shù)據(jù)庫連接,但是這和調(diào)用它的Dispose()有一些差別:Dispose()方法將調(diào)用GC.SuppressFinalize()方法,而Close()方法一般則不會(huì),因此,即使已經(jīng)不需要終結(jié),但對(duì)象仍舊在終結(jié)隊(duì)列中。如果兩種方式你可以選擇,應(yīng)該優(yōu)先使用Dispose方法。
同時(shí)我們需要知道:Dispose()并不是將對(duì)象從內(nèi)存中移除,而只是讓對(duì)象釋放掉其中的非托管資源。
7.避免創(chuàng)建非必要的對(duì)象
將常用的局部變量提升為成員變量:
所有的引用類型,包括那些局部變量,都會(huì)分配到堆上。在函數(shù)退出后,函數(shù)內(nèi)的所有局部變量都會(huì)立即變成垃圾對(duì)象。所以我們可以得出結(jié)論:若是某個(gè)引用類型(值類型無所謂)的局部變量用于被頻繁調(diào)用的例程中,那么應(yīng)該將其提升為成員變量。這既有助于減輕GC的負(fù)擔(dān),也可以提升程序運(yùn)行的效率。
為常用的類型實(shí)例提供靜態(tài)對(duì)象:
靜態(tài)成員變量可以讓引用類型在類的各個(gè)實(shí)例中共享。我們可以通過提供了一個(gè)類,存放某個(gè)類型常用的實(shí)例的單例對(duì)象,這樣可以避免創(chuàng)建重復(fù)的對(duì)象。
為不可變類型提供可變的創(chuàng)建方式:string.Format("{0},a}"