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

在.NET程序中正確使用String類型[2]

2013-11-13 12:15:16  來源: .NET編程 
    再看第()段代碼生成的指令

locals init ([] string s)
IL_: nop
IL_: ldstr abcd
IL_: stloc
IL_: ret
  可以很清楚地看到第()段代碼將導致String類的Concat()方法被調用(實現字串加法運算)對於第()段代碼由於C#編譯器聰明地在編譯時直接將兩個字串合並為一個字串字面量所以程序運行時CLR只調用一次ldstr指令就完成了所有工作其執行速度誰快就不言而喻了!

  避免使用加法運算符連接不同類型的數據

  請看以下代碼

String str = += + ;
ConsoleWriteline(str);
  生成的MSIL指令為

maxstack
locals init ([] string str)
IL_: nop
IL_: ldstr +=
IL_: ldci xc
IL_b: box [mscorlib]SystemInt
IL_: call string [mscorlib]SystemString::Concat(object
object)
IL_: stloc
IL_: ldloc
IL_: call void [mscorlib]SystemConsole::WriteLine(string)
IL_c: nop
IL_d: ret
  可以清晰地看到這兩句C#代碼不僅導致了String類的Concat()方法被調用(IL_而且還引發了裝箱操作(IL_b)!
Concat()方法會導致CLR為新字串分配內存空間而裝箱操作不僅要分配內存還需要創建一個匿名對象對象創建之後還必須有一個數據復制的過程代價不菲!

  改為以下代碼

String str = +=;
ConsoleWrite(str);
ConsoleWriteLine();
  生成的MSIL指令為

maxstack
locals init ([] string str)
IL_: nop
IL_: ldstr +=
IL_: stloc
IL_: ldloc
IL_: call void [mscorlib]SystemConsole::Write(string)
IL_d: nop
IL_e: ldci xc
IL_: call void [mscorlib]SystemConsole::WriteLine(int)
IL_: nop
IL_: ret


  可以看到雖然多了一次方法調用(ConsoleWrite)方法但卻避免了復雜的裝箱操作也避免了調用StringConcat()方法對內存的頻繁分配操作性能更好

  .在循環中使用StringBuilder代替String實現字串連接

  在某些場合需要動態地將多個子串連接成一個大字串比如許多復雜的SQL命令都是通過循環語句生成的這時應避免使用String類的加法運算符舉個簡單的實例

String str =;
for (int i = ; i <= ; i++)
{
str += i;
if(i<)
str += +;
}
  上述代碼將生成一個字串++…+

  有了前面的知識讀者一定知道這將導致進行次裝箱操作次字串內存分配操作(由StringConcat()方法引發)由於生成的MSIL指令太長此處不再列出請讀者自行用ildasmexe工具查看上述代碼生成的MSIL指令

  改為以下代碼程序性能會好很多

//預先分配K的內存空間
StringBuilder sb = new StringBuilder();
for (int i = ; i <= ; i++)
{
sbAppend(i);
if(i<)
sbAppend(+);
}
String result = sbToString();
  通過使用ildasmexe工具查看生成的MSIL代碼發現雖然上述代碼生成的MSIL指令比前面多了但卻避免了耗時的裝箱操作而且內存分配的次數也少了很多當循環的次數很大時兩段代碼的運行性能差異很大

[]  []  


From:http://tw.wingwit.com/Article/program/net/201311/15506.html
    Copyright © 2005-2013 電腦知識網 Computer Knowledge   All rights reserved.