// Bad
short shortNum;
int i = 32768;
shortNum = (short) i;
// problem after statment excution
// the shortNum variable has an uninitialized value,
// Good
try {
shortNum = checked((short)i); // solution
}
catch(OverflowException efx) {}
28 9月 2011
[C#] 用 checked 來避免溢位
當進行強制轉換時,容易因為長短不同而造成溢位(overflow)
[C#] 用 as 取代強制型態轉換
as 並不會回傳 exception,當無法轉換時會回傳 null
// Bad
object o = 1.3;
try
{
string str = (string)o;
}
catch(InvalidCastException ex){...}
// Good
string str = o as string;
if(null != str){...}
[C#] 善用 foreach 與 for
foreach 和 for 具有相同的目標:在一個區塊內反覆執行。
主要的不同點在於 foreach 不需要處理結束回圈的條件,此外,foreach 主要是設計於找尋全部的的資料,因此 foreach 可以是 for 方法中的一個例子。
在 .NET 1.0 之前 foreach 的效率較差,在 .NET 1.1 之後 foreach 與 for 效能差不多,但是MSDN的建議:對於處理大量的資料下 for 的效能會比 foreach 來的好。
主要的不同點在於 foreach 不需要處理結束回圈的條件,此外,foreach 主要是設計於找尋全部的的資料,因此 foreach 可以是 for 方法中的一個例子。
在 .NET 1.0 之前 foreach 的效率較差,在 .NET 1.1 之後 foreach 與 for 效能差不多,但是MSDN的建議:對於處理大量的資料下 for 的效能會比 foreach 來的好。
// foreach
int[] arrayOfInts= new int[5];
int sum= 0;
foreach(int i arrayOfInts)
{
sum+= i;
}
// for
int[] arrayOfInts= new int[5];
int sum= 0;
for(int i = 0; i < arrayOfInts.Length; i++)
{
sum+= arrayOfInts[i];
}
[C#] 用 nGen.exe 來提升初始化效能
一般來說,Managed 可執行檔內的方法都會經過 Just-In-Time (JIT) 編譯。而一旦有了執行執行檔的處理序之後,JIT 編譯器所產生的機器碼就被棄置,所以下回再度執行應用程式時,就必須再次編譯方法。此外,所產生的程式碼和建立它的處理序之間關係緊密,其他執行同一個應 用程式的處理序並無法共用這些程式碼。
上述這些 .NET JIT 的編譯特色可能會導致效能方面的缺失,不過幸好有 NGen (原生影像產生),有助問題的化解。NGen 指的是將 Microsoft® Intermediate Language (MSIL) 可執行檔在執行前先行編譯成機器碼的這個過程,如此能在兩方面大幅提昇效能。首先,這樣可縮減應用程式的啟動時間,避免在執行階段編譯程式碼;其次,它可以改善記憶體的使用,允許跨多個處理序共用字碼頁。乍看之下,NGen 似乎跟傳統的靜態末端編譯十分類似,然而實際上它們迥然不同。由於 NGen 影像一定要存放在用來建立它們的機器上,不然就無法被部署,因此它和靜態編譯的二進位碼檔案並不相同。相反的,應用程式的安裝程式必須發佈命令,在安裝時 期於用戶端機器上建立組件原生影像。另一個與傳統二進位碼檔案不同的地方是,NGen 影像只會形成 Cache-managed 應用程式,所以即使刪除了所有的 NGen 影像,應用程式仍可正常運作。當然啦,如果真的是那樣的話,效能可能會受到大幅影響,不過對正確度則沒有任何影響。但是如果 MSIL 組件在編譯成 NGen 影像後就被刪除,則 Managed 應用程式就無法正確運作。
ngen [options] [assemblyName |assemblyPath ]
參考資料
1. NGen 所帶來的效能優勢
[C#] 用 String.Equal 方法取代 == 運算子
當字串相似時,使用 string.Equals 方法將會比較快速
因此,如果能預期在某一特定型態下,且預期大部分
的字串會相同的話,請使用 Equals
因此,如果能預期在某一特定型態下,且預期大部分
的字串會相同的話,請使用 Equals
string s1= "code";
string s2 = "code1";
// Bad
if(s1 == s2){...}
// Good
if(s1.Equals(s2)){...}
[C#] 盡量避免用 Boxing 和 Unboxing
Boxing 某個型態的數值時會包含下列兩個行程
當使用 ArrayList 時,儘量避免使用 struct 的型態,因為 ArrayList 將會使用
object 來置換 struct 的型態;當程序在迴圈內執行時,Boxing 將會一直發生
而在 Unboxing 時,也會執行下列兩個行程
- 分配一個物件
- 將該型態的資料複製於物件
當使用 ArrayList 時,儘量避免使用 struct 的型態,因為 ArrayList 將會使用
object 來置換 struct 的型態;當程序在迴圈內執行時,Boxing 將會一直發生
而在 Unboxing 時,也會執行下列兩個行程
- 建置型態
- 複製資料
// Badstruct st
{
public Int i;
}
Arraylist arr = new ArrayList();
for (int i=0 ; i< 4; i++)
{
st s;
s.i = 4;
arr.add(st) ; // Boxing
}
st obj = (st ) arr[0]; // Unboxing
// Good
Class st
{
public Int i;
}
List arr = new List();
for (int i=0 ; i< 4; i++)
{
st s;
s.i = 4;
arr.add(st);
}
st obj = arr[0];
27 9月 2011
[C#] 用 StringBuilder 取代 string 的字串連接
C#中使用 string 是不可改變的,即不能更改
當你改變一個字符串,你實際上是在創建一個新的字符串,導致:
當你改變一個字符串,你實際上是在創建一個新的字符串,導致:
- 程式碼將會使用更多而不必要的記憶體
- 將會有更多的垃圾需要回收(GC)
- 執行速度將會變慢
// Bad
String strConcat;
ArrayList arrayOfStrings = new ArrayList();
arrayOfStrings.Add("a");
arrayOfStrings.Add("b");foreach (string s in stringContainer)
{
strConcat += s;
}
// Good
StringBuilder sbConcat = new StringBuilder ();
foreach (string s in arrayOfStrings )
{
sbConcat.append(s);
}
[C#] 當檢查字串長度時,使用Length
字串比較容易造成不必要的負擔
若要判定字串是否是空的長度,請使用 Length 屬性
.Net 2.0 之後的版本亦可使用 string.IsNullOrEmpty()
.Net 2.0 之後的版本亦可使用 string.IsNullOrEmpty()
// Bad
if ( str != "")
{
...
}
// Good
if ( str.Length > 0)
{
...
}
訂閱:
文章 (Atom)