string注意事項
我認爲對基礎的理解是否深刻,才是判斷對知識掌握的判定標準。
今天我們來討論下,在.net編程中使用最頻繁的類string的幾個需要注意的地方。
MSDN中對string 解釋為字符串是 Unicode 字符的有序集合,用于表示文本。String 对象是 System..::.Char 对象的有序集合,用于表示字符串。
String 对象的值是该有序集合的内容,并且该值是不可变的。
String 对象称为不可变的(只读),因为一旦创建了该对象,就不能修改该对象的值。看来似乎修改了 String 对象的方法实
际上是返回一个包含修改内容的新 String 对象。
這裡我們有兩個問題要討論,其
一是string對象,其二字符串
前者指system.string類,後者指""之間的字符
我們先討論後者
這裡我們要引入一個概念字符串驻留(String Interning)
MSDN中對字符串驻留討論為
公共语言运行库通过维护一个表来存放字符串,该表称为“拘留池”,它包含程序中以编程方式声明或创建的每个唯一的字符串的一个引用。因此,具有特定值的字符串的实例在系统中只有一个。
例如,如果将同一字符串分配给几个变量,运行库就会从拘留池中检索对该字符串的相同引用,并将它分配给各个变量。
也就是說例如
string a="a";
a+="b";
實際上是分別在拘留池中創建了"a","b"
就結論而言,就是説由於string,很重要,且使用相當頻繁以至于CLR必须以特殊的方式来实现对string类型的管理、存取和布局。
在这些复杂的特殊表象中,字符串驻留机制是string特殊性的集中体现,它的基本原理可以概括为:
* CLR维护一个类似于哈希表的内部结构,用于维护对于字符串的统一管理。
* 但JIT编译时,CLR首先查找哈希表,如果没有找到匹配的字符串记录,则在托管堆中创建新的string实例,并为哈希表添
加一个键值对记录;下一次查找相同string时,则只返回该记录的值给第二次创建的string对象。
* 通过这种方式,字符串驻留机制有效实现了对string的池管理,节省了大量的内存空间。
我們可以通過string.IsInterned(string)來判斷是否該string存在于 拘留池中
通過多次試驗,我們們可以得出這樣一系列結論
1、所有被引用的string對象都會存放内存中 拘留池,
2、該拘留池 是已类似于哈希表分佈的,只有明文存在的string對象才會被保存在拘留池中
(例如Console.WriteLine("ab");時拘留池存在"ab",string a="a";a+="b";時拘留池不存在"ab")
3、若是存在于方法,或其他類型的方法中返回存在的字符,必須被調用后才存放在拘留池
被定義(如string a="ab")或直接輸出(Console.WriteLine("ab");),則在執行該語句之前已先一步進入拘留池中。
通過以上的資料,和實際試驗,我們可以發現,在我們最常用的字符串拼接的時候,在我們獲得需要的string對象前,或在拘留池中存放大量的,string對象,會對CG機制造成壓力。
而科學的切割字符串,讓相同部分和不同部分合理分開,會良好的利用哈希結構的高效性,讓重復執行的代碼,獲得更高的速度。
而過多的,或是用並不頻繁的字符串拼接,我們就不僅僅要考慮 字符串的駐留問題了
我們就要考慮是使用string 或 StringBuilde類。以及他們各自特點問題了。
StringBuilde該對象是 “表示可变字符字符串”。
對此MSDN中解釋為:
String 对象串联操作总是用现有字符串和新数据创建新的对象。
StringBuilder 对象维护一个缓冲区,以便容纳新数据的串联。如果有足够的空间,新数据将被追加到缓冲区的末尾;否则,将分配一个新的、更大的缓冲区,原始缓冲区中的数据被复制到新的缓冲区,然后将新数据追加到新的缓冲区。
String 或 StringBuilder 对象的串联操作的性能取决于内存分配的发生频率。
String 串联操作每次都分配内存,而 StringBuilder 串联操作仅当 StringBuilder 对象缓冲区太小而无法容纳新数据时才分配内存。
因此,如果串联固定数量的 String 对象,则 String 类更适合串联操作。
这种情况下,编译器甚至会将各个串联操作组合到一个操作中。(編譯器優化)
如果串联任意数量的字符串,则 StringBuilder 对象更适合串联操作;
例如,某个循环对用户输入的任意数量的字符串进行串联。
最後我們判斷到底是否使用String 或 StringBuilder
基本結論應該是,,,
不對字符串進行更改時使用string
當字符串連接數量少,長度不大時使用String ,
大量使用到連接,長度又很長時使用StringBuilder
前者因爲StringBuilder對象創建時速度比string慢
后者因爲string的不變性,大長字段的拼接造成内存中大量無用的string存在
對CG造成巨大壓力性能大大降低。
綜上所訴,我們使用string時,
1、考慮StringBuilder對象以及string對象針對不同情況的選取。
2、對字符串切割時,考慮字符串内存駐留問題。
我們就能良好的把握這個string 編程中使用最頻繁的對象了。