建議1:正確使用字串
string
string str1 = "str1" + 9;string str2 = "str2" + 9.ToString();
第一行代碼會產生一次裝箱,還有一次string的concat
而第二行代碼使用ToString(),內部使用的是Number.FormatInt32
其原型為
而NumberFormatInt32是一個非託管方法,運行效率比正常c#的Managed 程式碼要高很多,所以第二行代碼的效率比第一行高
至於什麼是Managed 程式碼Unmanaged 程式碼,我引用了其他部落格的一段話:
Managed 程式碼與Unmanaged 程式碼眾所周知,我們正常編程所用的進階語言,是無法被電腦識別的。需要先將進階語言翻譯為機器語言,才能被機器理解和運行。 在標準C/C++中,編譯過程是這樣的:
原始碼首先經過前置處理器,對標頭檔以及宏進行解析,然後經過編譯器,產生彙編代碼,接著,經過彙編,產生機器指令,最後將所有檔案串連起來。 這種編譯方式的優點在於,最終直接產生了機器碼,可以直接被電腦識別和運行,無需任何中間運行環境,但缺點也在於,由於不同平台能夠識別的機器碼不同,因此程式的跨平台能力較差。 而在Java語言中,原始碼並沒有被直接翻譯成機器碼,而是編譯成了一種中間代碼(位元組碼Bytecode)。因此,運行Java程式需要一個額外的JRE(Java Runtime Enviromental)運行環境,在JRE中存在著JVM(Java Virtual Mechinal,Java虛擬機器),在程式啟動並執行時候,會將中間代碼進一步解釋為機器碼,並在機器上運行。 使用中間代碼的好處在於,程式的跨平台性比較好,一次編譯,可以在不同的裝置上運行。 託管/非託管是微軟的.net framework中特有的概念,其中,Unmanaged 程式碼也叫本地(native)代碼。與Java中的機制類似,也是先將原始碼編譯成中間代碼(MSIL,Microsoft Intermediate Language),然後再由.net中的CLR將中間代碼編譯成機器代碼。 而C#與Java的區別在於,Java是先編譯後解釋,C#是兩次編譯。 託管的方式除了擁有跨平台的優點之外,對程式的效能也產生一定的影響。但程式效能不在本文討論的範圍,這裡不在贅述。 此外,在.net中,C++也可以進行託管擴充,從而使C++代碼也依賴於.net和CLR運行,獲得Managed 程式碼的優勢。 |
簡單理解就是Managed 程式碼加了一個中介層,使其可以跨平台,不過效率會降低,而Unmanaged 程式碼就不會產生這樣的情況
所以我們編寫代碼秉承一個原則:盡量減少裝箱拆箱
StringBuilder
StringBuilder的效率來源於預先以非託管的方式分配記憶體,如果沒有預先定義長度,預設長度為16,不夠的時候會重新分配記憶體,依次加16的倍數,所以如果你提前知道字串需要的最大長度,最好預先定義好,這樣就不會頻繁分配記憶體從而帶來效率的降低
2、使用預設轉型方法
這個建議的大體內容是盡量使用系統所帶的轉換類型的方法
例如 int.Parse ToString() System.Convert 等等
3、區別對待強轉類型和as is
兩個類型之間轉換有兩種情況
1. 他們是父子類的關係: ChildType = (ChildType)ParentType
2.沒有繼承關係,或者繼承同一個父類,這時候就需要重寫強轉方法
class FirstType{ public string Name { get; set; }}class SecondType{ public string Name { get; set; } public static explicit operator SecondType(FirstType firstType) { SecondType secondType = new SecondType() { Name = firstType.Name }; return secondType; }}FirstType firstType = new FirstType() { Name = "張" };SecondType secondType = (SecondType)firstType;
如果是繼承的關係,為了效率推薦使用 ChildType = ParentType as ChildType
這個就更上面提到的,盡量使用系統方法的轉換,而不是強制轉換
我寫Unity的時候有這樣一個需求,右鍵點擊裝備的時候會使用,裝備有Equipment,Weapon,我們需要判斷是Equipment還是Weapon類型,它們都是繼承Item類型,有兩種方法可用:
Weapon weapon = item as Weapon;if(weapon != null){ //TODO 使用武器}if(item is Weapon){ weapon weapon = item as Weapon; //TODO 使用武器}
第一種方法只判斷了一次類型,而第二種方法判斷了兩次類型
書上說as不能判斷基元類型,但是經過我的測試發現書上寫錯了,as僅僅不能判斷實值型別,這裡大家可以自己測試一下
相關文章:
C#學習記錄:編寫高品質代碼改善整理建議4-8
C#學習記錄:編寫高品質代碼改善整理建議9-15