第一篇: 你真的了解.net中的string 注:來自於網路
string在任何語言中,都有它的特殊性,在.net中也是如此。它屬於基本資料型別,也是基本資料型別中唯一的引用型別。字串可以宣告為常量,但是它卻放在了堆中。希望通過本文能夠使大家對.net中的string有乙個深入的了解。
一:不可改變物件
在.net中string是不可改變物件,一旦建立了乙個string物件並為它賦值,它就不可能再改變,也就是你不可能改變乙個字串的值。這句話初聽起來似乎有些不可思議,大家也許馬上會想到字串的連線操作,我們不也可以改變字串嗎?看下面這段**:
1 using system;
2 3 namespace demo1
4 19 }
20 }
21 執行的結果:
1234
12345678
看起來我們似乎已經把mystr的值從「1234」改為了「12345678」。事實是這樣的嗎?實際上並沒有改變。在第5行**中建立了乙個string物件它的值是「1234」,mystr指向了它在記憶體中的位址;第七行**中建立了乙個新的string物件它的值是「12345678」,mystr指向了新的記憶體位址。這時在堆中其實存在著兩個字串物件,儘管我們只引用了它們中的乙個,但是字串「1234」仍然在記憶體中駐留。
二:引用型別
前面說過string是引用型別,這就是如果我們建立很多個相同值的字串物件,它在記憶體中的指向位址應該是一樣的。也就是說,當我們建立了字串物件a,它的值是「1234」,當我們再建立乙個值為「1234」的字串物件b時它不會再去分配一塊記憶體空間,而是直接指向了a在記憶體中的位址。這樣可以確保記憶體的有效利用。看下面的**:
1 using system;
2 3 namespace demo2
4 21
22 public static void change(string s)
23
26 }
27 }
執行結果:
1234
1234
做乙個小改動,注意change(ref string s)
1 using system;
2 3 namespace demo2
4 21
22 public static void change(ref string s)
23
26 }
27 }
28 執行結果:
1234
5678
三:字串的比較
在.net中,對字串的比較操作並不僅僅是簡單的比較二者的值,==操作首先比較兩個字串的引用,如果引用相同,就直接返回true;如果不同再去比較它們的值。所以如果兩個值相同的字串的比較相對於引用相同的字串的比較要慢,中間多了一步判斷引用是否相同。看下面這段**:
1 using system;
2 3 namespace demo3
4 7 if ((a != null) && (b != null))
8
11 return false;
12 }
13 四:字串駐留
看一下這段**:
1 using system;
2 3 namespace demo4
4 23 }
24 }
25 執行的結果:
false
true
在這段**中,比較這兩個物件發現它的引用並不是一樣的。如果要想是它們的引用相同,可以用intern()函式來進行字串的駐留(如果有這樣的值存在)。
三:stringbuilder物件
通過上面的分析可以看出,string型別在做字串的連線操作時,效率是相當低的,並且由於每做乙個連線操作,都會在記憶體中建立乙個新的物件,占用了大量的記憶體空間。這樣就引出stringbuilder物件,stringbuilder物件在做字串連線操作時是在原來的字串上進行修改,改善了效能。這一點我們平時使用中也許都知道,連線操作頻繁的時候,使用stringbuilder物件。但是這兩者之間的差別到底有多大呢?來做乙個測試:
1 using system;
2 using system.text;
3 4 namespace demo5
5 // end of method class1::main
34 *
35 相信通過上面的**和反編譯後的結果,大家可以看的很清楚,string如何被分配,而在你重新修改string的時候,是如何工作..既然發現了問題,當然也可以解決問題所在..解決和優化的辦法很多,我只簡單的列出幾種,第一種,使用string陣列來代替..看下面**:
1 string arr1 = new string[4];//聲名需要內建4個string
2 arr1[0] = "1";//內建了1
3 arr1[1] = "2";//內建了2
4 arr1[2] = "3";//內建了3
5 arr1[3] = "4";//內建了4
6 /*陣列賦值後,在il反編譯後的表現
7 *
8 *
9 *.method private hidebysig static void main(string args) cil managed
10 // end of method class1::main
37 *
38 * */
看看上面的**,我想很明白,string是如何工作的了吧??可以這麼理解:每個陣列的子項都是乙個被內建的string!!
第二種解決辦法是char,如果你知道你的字串大小,可以這麼寫char c = new char[4];這個做法在c/c++中是很不錯的,但是在c#似乎用的不多,而且用起來也比較麻煩.因為它不能想c/c++這樣: char c = ;不過我依然在做乙個加密/解密類的時候用了char!!
最後一種也是最常用的:stringbuilder,既然string有重新分配位址的***.所以微軟也為我們提供了stringbuilder來解決這個問題..
第三篇: stringbuilder的實現與技巧
通過上面的**,我們可以看出如果stringbuilder 中的字元長度小於length的值,則stringbuilder 將會用空格硬填充stringbuilder ,以滿足符合長度的設定..如果stringbuilder 中的字元長度大於length的值,則stringbuilder 將會擷取從第一位開始的length個字元..而忽略超出的部分..
上面的**輸出的結果:
1 capacity:16 length:0 //輸出第一次,預設的capacity是16
2 capacity:32 length:17 //第二次,我們故意新增了17個字元,於是capacity=capacity*2
3 capacity:64 length:49 //繼續超出,則capacity=capacity*2
4 capacity:128 length:113
5 capacity:3 length:2 //清空內容後,設定capacity=1,重新新增了字元
6 capacity:7 length:6 //後面的結果都類似
7 capacity:14 length:12
String型別詳解
字串是乙個特殊的物件,從api文件的對string宣告 public final class 中可以看出該類不可以被繼承。以上是對字串的描述,接下來通過例項展現string的型別的一些用法 很多人碰到這個問題 string s 123 這裡有幾個物件。在這裡,s為類型別變數,123 為乙個物件。變數...
C 之string型別詳解
from 之所以拋棄char 的字串而選用c 標準程式庫中的string類,是因為他和前者比較起來,不必擔心記憶體是否足夠 字串長度等等,而且作為乙個泛型類出現,他整合的操作函式足以完成我們大多數情況下 甚至是100 的需要。我們可以用 進行賦值操作,進行比較,做串聯 是不是很簡單?我們盡可以把它看...
String用法詳解
include 注意這裡不是string.h,string.h是c字串標頭檔案這樣我們就宣告了乙個字串變數,但既然是乙個類,就有建構函式和析構函式。上面的宣告沒有傳入引數,所以就直接使用了string的預設的建構函式,這個函式所作的就是把str初始化為乙個空字串。string類的建構函式和析構函式如...