一、前言
昨天在群里討論怎么樣效率的把一個字符串進行反轉,一般的情況我們都知道,只要對String對象進行操作,
那么就會生成新的String對象,比如"1"+"2" 這樣的操作會生成新的String對象。
二、通正方案
通常我們要反轉一個字符中我們都是使用如下方法:
static string Reverse1(string original) { char[] arr = original.ToCharArray(); Array.Reverse(arr); return new string(arr); }
這種方式,只是通過將數組反轉的方式重新排列了字符的順序,最終還是要重新生成新的String對象,這樣無疑會在數據量比較大的時候,會增加GC負擔的。
三、unsafe方案
本文主要想講述使用**unsafe**的方式來優化性能,當然在最后面還提到了**c# 7.0**中的新特性來實現相同功能。
unsafe關鍵字表示不安全上下文,該上下文是任何涉及指針的操作所必需的。有關更多信息,請參見不安全代碼和指針(C# 編程指南)。
可以在類型或成員的聲明中使用 unsafe 修飾符。因此,類型或成員的整個正文范圍均被視為不安全上下文。
c#在默認情況下生成的都是安全代碼,即進行了代碼托管(.NET的CLR機制好處之一就是自動進行代碼托管,適時的釋放內存,程序員便不必考慮資源的回收問題),而此時,指針不能出現在安全代碼的編譯條件下。
如果因需要想在c#中使用指針,那么unsafe便是一個通道(當然在使用前,需在項目屬性的生成選項中,選擇“允許不安全代碼”)。
直接上代碼吧:
string hello = "hello world你好"; int len = hello.Length * 2; fixed (char* strs = hello) { byte* start = (byte*)strs; byte* end = start + len - 1; byte[] ch = new byte[2]; if (start != null) { while (start < end) { ch[0] = *start; ch[1] = *(start + 1); *start = *(end-1); *(start+1) = *(end); start = start + 2; *(end - 1) = ch[0]; *(end) = ch[1]; end = end - 2; } } }
fixed 語句設置指向托管變量的指針並在 statement 執行期間“釘住”該變量。如果沒有 fixed 語句,則指向可移動托管變量的指針的作用很小,因為垃圾回收可能不可預知地重定位變量。C# 編譯器只允許在 fixed 語句中分配指向托管變量的指針。(這句話是機器翻譯的,呵呵)
好了最終的結果就是: hello="好你dlrow olleh" , 但是我們並沒有new String哦!
四、C#7 Ref locals ?
其實對說新的C# 7.0來說,它為我們帶來了新ref關鍵字,來處理本地引用(Ref locals )。
讓我們來開一下腦洞,下面是段成立的代碼:
string hello = "hello world你好"; ref char strRef = ref getStringArray(ss, 0); static ref char getStringArray(char[] str,int index) { return ref str[index]; }
strRef是什么?我們是不是可以通過這樣的方式,來達到與使用指針相同的目地?請繼續關注下一篇文章。
同時宣傳一下我的新博客,當然博客園我也會更新的。 http://www.dotnet.ren
