小編給大家分享一下C#中怎么使用字符串String,相信大部分人都還不怎么了解,因此分享這篇文章給大家參考一下,希望大家閱讀完這篇文章后大有收獲,下面讓我們一起去了解一下吧!
公司主營業(yè)務(wù):成都網(wǎng)站制作、做網(wǎng)站、外貿(mào)營銷網(wǎng)站建設(shè)、移動網(wǎng)站開發(fā)等業(yè)務(wù)。幫助企業(yè)客戶真正實現(xiàn)互聯(lián)網(wǎng)宣傳,提高企業(yè)的競爭能力。成都創(chuàng)新互聯(lián)是一支青春激揚(yáng)、勤奮敬業(yè)、活力青春激揚(yáng)、勤奮敬業(yè)、活力澎湃、和諧高效的團(tuán)隊。公司秉承以“開放、自由、嚴(yán)謹(jǐn)、自律”為核心的企業(yè)文化,感謝他們對我們的高要求,感謝他們從不同領(lǐng)域給我們帶來的挑戰(zhàn),讓我們激情的團(tuán)隊有機(jī)會用頭腦與智慧不斷的給客戶帶來驚喜。成都創(chuàng)新互聯(lián)推出任城免費做網(wǎng)站回饋大家。
前言
C#中提供了比較全面的字符串處理方法,很多函數(shù)都進(jìn)行了封裝為我們的編程工作提供了很大的便利。System.String是最常用的字符串操作類,可以幫助開發(fā)者完成絕大部分的字符串操作功能,使用方便。
字符串作為所有編程語言中使用最頻繁的一種基礎(chǔ)數(shù)據(jù)類型。如果使用不慎,將會造成不必要的內(nèi)存開銷,為此而付出代價。
而要優(yōu)化此類型,從以下兩點入手:
1、盡量少的裝箱
2、避免分配額外的內(nèi)存空間
先從第一點裝箱的操作說起,查看如下代碼:
//發(fā)生裝箱的代碼 String boxOperate = "test" + 4.5f;
其中間語言IL代碼為如下:
IL_0000: nop IL_0001: ldstr "test" IL_0006: ldc.r4 4.5 IL_000b: box [mscorlib]System.Single IL_0010: call string [mscorlib]System.String::Concat(object, object) IL_0015: stloc.0 IL_0016: call valuetype [mscorlib]System.ConsoleKeyInfo [mscorlib]System.Console::ReadKey() IL_001b: pop IL_001c: ret
不難看出,上述代碼發(fā)生了裝箱的操作(IL代碼中的box).裝箱之所以會發(fā)生性能損耗,因為它要完成如下三個步驟:
1、首先,會為值類型在托管堆中分配內(nèi)存。除了值類型本身所分配的內(nèi)存外,內(nèi)存總量還要加上類型對象指針和同步塊索引所占用的內(nèi)存,
2、將值類型的值復(fù)制到新分配的堆內(nèi)存中。
3、返回已經(jīng)成為引用類型的對象的地址。
在來看以下代碼:
//沒有發(fā)生裝箱的代碼 String boxOperate = "test" + 4.ToString();
其中間IL代碼如下:
IL_0000: nop IL_0001: ldstr "test" IL_0006: ldc.r4 4 IL_000b: stloc.1 IL_000c: ldloca.s 1 IL_000e: call instance string [mscorlib]System.Single::ToString() IL_0013: call string [mscorlib]System.String::Concat(string, string) IL_0018: stloc.0 IL_0019: call valuetype [mscorlib]System.ConsoleKeyInfo [mscorlib]System.Console::ReadKey() IL_001e: pop IL_001f: ret
如上,并沒有發(fā)生任何裝箱操作,但是達(dá)到的結(jié)果卻是我們想要的。原因是 4.ToString() 這行代碼并沒有發(fā)生裝箱行為,是實際調(diào)用的是整數(shù)型的ToString()方法,其原型如下:
public override string ToString(){ return Number.FormatInt32(m_value, null, NumberFormat.CurrentInfo); }
可能有人會問,是不是原型中的 Number.Format_XXX方法會發(fā)生裝箱行為呢?實際上,Number.Format_XXX方法是一個非托管的方法,其原型如下:
[MethodImpl(MethodImplOptions.InternalCall), SecurityCritical]
public statuc extern string FormatInt32(int value, string format,NumberFormatInfo info);
它是通過直接操作內(nèi)存來完成 Int32 到 String 的轉(zhuǎn)換,效率要比裝箱高得多。所以,在使用其他值引用類型到字符串得轉(zhuǎn)換比完成拼接時,應(yīng)當(dāng)避免使用操作符 “+” 來我完成,而應(yīng)該使用值引用類型提供得ToString方法。
也許有人會問:即使FCL提供得方法沒有發(fā)生裝箱行為,但在其他情況下,F(xiàn)CL方法內(nèi)部會不會含有裝箱的行為?也許會存在,所以,本人推薦:編寫代碼中,應(yīng)當(dāng)盡量避免發(fā)生不必要的裝箱代碼。
第二個方面:避免分配額外的空間。對于CLR來說,String對象(字符串對象)是個很特殊的對象,它一旦被賦值就不可改變(在內(nèi)存中)。在運(yùn)行時調(diào)用System.String類中的任何方法或進(jìn)行任何運(yùn)算('=‘賦值,'+‘拼接等),都會在內(nèi)存中創(chuàng)建一個新的字符串對象,這也意味著要為該新對象分配新的內(nèi)存空間。如以下代碼會帶來額外開銷。
private static void Test(){ String str1 = "aa"; str1 = str1 + "123" + "345"; //以上代碼創(chuàng)建了3個String對象,并執(zhí)行了一次String.Contact方法。 }
而在以下代碼中,字符串不會在運(yùn)行時拼接字符串,而是會在編譯時直接生成一個字符串。
private static void Test() { String str= "aa" + "123" + "345";//等效 String str= "aa123345"; } private static void Test2() { const String str = "aa"; String newStr = "123" + str; //因為str是一個常量,所以該代碼等效于 String newStr = "123" + “aa”; //最終等效于 String newStr = "123aa”; }
由于使用System.String類會在某些場合帶來明顯的性能損耗,所以微軟另外提供了一個類型StringBuilder來彌補(bǔ)String的不足。
StringBuilder并不會重新創(chuàng)建一個String對象,它的效率源于預(yù)先以非托管的方式分配內(nèi)存。如果StringBuilder沒有先定義長度,則默認(rèn)分配的長度為16。當(dāng)StringBuilder的長度大于16小于32時,StringBuild又會重新分配內(nèi)存,使之成為16的倍數(shù)。StringBuilder重新分配內(nèi)存時按照上次的容量加倍進(jìn)行分配的。注意:StringBuilder指定的長度要合適,太小了,需要頻繁分配內(nèi)存;太大了,浪費內(nèi)存空間。
以下是例子舉例:
private static String Test3() { String a = "t"; a += "e"; a += "s"; a += "t"; return a; } private static String Test4() { String a = "t"; String b = "e"; String c = "s"; String d = "t"; return a + b + c + d; } //以上兩種效率都不高效。不要以為前者比后者創(chuàng)建的字符串對象更少,事實上,兩者創(chuàng)建的字符串對象相等 //且前者進(jìn)行了3次的String.Contact方法調(diào)用,比后者還多了兩次。
要完成上圖的運(yùn)行時的字符串拼接(注意:是運(yùn)行時),更佳的做法是使用StringBuilder類型,代碼如下:
private static String Test5() { String a = "t"; String b = "e"; String c = "s"; String d = "t"; StringBuilder sb = new StringBuilder(a); sb.Append(b); sb.Append(c); sb.Append(d); return sb.ToString(); //因為說的是運(yùn)行時,所以沒必要使用以下代碼 //StringBuilder sb = new StringBuilder("t"); //sb.Append("e"); //sb.Append("s"); //sb.Append("t"); //return sb.ToString(); }
微軟還提供了另外一個來簡化這種操作,即使用String.Format 方法。String.Format方法在內(nèi)部使用StringBuilder 進(jìn)行字符串格式化,如下圖代碼:
private static String Test6() { //為演示,定義4個變量 String a = "t"; String b = "e"; String c = "s"; String d = "t"; return String.Format("{0}{1}{2}{3}", a, b, c, d); }
以上是“C#中怎么使用字符串String”這篇文章的所有內(nèi)容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內(nèi)容對大家有所幫助,如果還想學(xué)習(xí)更多知識,歡迎關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道!