.Net Framework中處理字符和字符串的主要有以下這么幾個類:
(1)、System.Char類 一基礎字符串處理類
(2)、System.String類 一處理不可變的字符串(一經創建,字符串便不能以任何方式修改)
(3)、System.Text.StringBuilder類 一更高效地構建字符串
(4)、System.Secureity.SecureString類 一對字符串進行保護操作,它可以保護密碼和信用卡資料等敏感字符串.
一、String類型
1、簡介
在任何應用程序里面,String類型都是用的最多的類型之一.一個String代表一個不可變的(immutable)的順序字符串,String類型直接派生自Object,所以它是引用類型.所以String對象(它的字符串數組)總是存在於堆上,永遠不會跑到線程棧.
C#將String視為基元類型,C#編譯器允許在源代碼中直接使用字面值字符串.編譯器將這些字符串存放到模塊的元數據中,並在運行時加載和引用它們.
C#不允許使用new操作符從字面值字符串構造String對象,代碼如下:
相反,必須使用以下簡化語法:
編譯代碼並檢查IL(使用ILDasm.exe),會看到以下內容:
用於構造對象新實例,但上述代碼中並沒有出現newobj指令,有一個特殊的ldstr(即 load string)指令,它使用從元數據獲得的字面值(literal)字符串構造String對象.這證明CLR實際是用一種特殊方式構造字面值String對象
如果使用不安全的(unsafe)代碼,可以從一個Char*或Sbyte*參數構造一個String.這時要使用C#的new操作符,並調用由String類型提供的、能接受Char*或Sbyte*參數的某個構造器.這些構造器將創建String對象,根據由Char實例或有符號(signed)字節構成的一個數組來初始化字符串。其他構造器則不允許接受任何指針參數,用任何托管編程語言寫的安全(可驗證)代碼都能調用它們.
2、關於特殊字符的處理:
C#提供了一些特殊的語法來幫助開發人員在源代碼中輸入字面值(literal)字符串,對於換行符、回車符和退格符這樣的特殊字符,C#采用的是C/C++開發人員熟悉的轉移機制,代碼如下:
//包含回車符和換行符的字符串 string s="Hi\r\nthere.";
3、關於字符串連接的問題
string s="Hi"+" "+"there .";
在上述代碼中,由於所有字符串都是字面值,所以C#編譯器能在編譯時連接它們,最終將一個字符串即(即"Hi there.")放到模塊的元數據中.對非字面值字符串使用+操作符,連接則在運行時進行.運行時連接不要用+操作符,因為這樣會在堆上創建多個字符串對象,而堆是需要垃圾回收的,對性能有影響.相反,應該使用StringBuilder類型.
4、字符串@轉義符
C#提供了一種特殊的字符串聲明方式.采取這種方式,印號之間的所有字符都會被視為字符串的一部分.這種特殊聲明稱為"逐字字符串",通常用於指定文件或目錄的路徑,或者與正則表達式配合使用。以下代碼展示了如何使用和不適用逐字字符串字符(@)來申明同一個字符串,代碼如下:
//指定應用程序路徑,使用\解析'\' string file="C:\\Windows\\System32\\Notpad.exe"; //使用逐字字符串制定應用程序路徑 string file=@"C:\Windows\System32\Notepad.exe";
兩種寫法生成完全一樣的字符串,但后者的可讀性更好.
5、字符串是不可變的
string對象最重要的一點就是不可變性.也就是所,字符串一經創建遍不能修改其中的任何字符.是字符串不可變有幾方面的好處.
字符串不可變有幾個方面的好處:
(1)、它允許在一個字符串上執行各種操作,而不實際地更改字符串,如下代碼:
//創建一個字符串 string str = "zhengchao"; //然后將字符串轉大寫,ToUpperInvariant會創建一個臨時字符串,垃圾回收器會在下次回收時回收 var result = str.ToUpperInvariant(); //輸出:false,說明ToUpperInvariant返回了一個新的字符串 Console.WriteLine("str:'{0}' is Equals result? The answer is {1}",str, ReferenceEquals(str, result)); //字符串截取,ToUpperInvariant會創建一個臨時字符串,垃圾回收器會在下次回收時回收 var result1 = result.Substring(2,3); //輸出:false,說明Substring返回了一個新的字符串 Console.WriteLine("str is Equals result? The answer is {0}", ReferenceEquals(result, result1)); //EndsWith對目標字符進行檢查不會創建臨時字符串 var result2 = result.EndsWith("ENG");
代碼不會長時間引用由ToUpperInvariant和Substring創建的兩個臨時字符串,垃圾回收器會在下次回收時回收它們的內存.如果執行大量字符串操作,會在堆上創建大量String對象,造成更頻繁的垃圾回收,從而影響應用程序性能.so,要高效執行大量字符串操作,建議使用StringBuilder類.
字符串的不可變意味着在操縱或訪問字符串時不會發生線程同步問題.此外,CLR可通過一個String對象共享多個完全一直的String內容.
這樣能減少系統中的字符串數量一從而節省內存一這就是所謂的"字符串留用".
(2)、實例唯一性
在內存中復制同一個字符串的實例純屬浪費,因為字符串是"不可變"的.在內存中只保留字符串的一個實例將顯著提升內存的利用率。需要引用字符串的所有變量只需指向單獨的一個字符串對象.
代碼如下:
string str1 = "xiaochao"; string str2 = "xiaochao"; Console.WriteLine(ReferenceEquals(str1, str2));//輸出:True,說明str1和str2實例指向的是同一個對象
出於對性能的考慮,String類型與CLR緊密集成.具體地說,CLR知道String類型中定義的字段如何布局,會直接訪問這些字段.但是為了獲得這種性能和直接訪問的好處,String只能是密封類.換言之,不能把它作為自己類型的基類.
如果允許String作為基類來定義自己的類型,就能添加自己的字段,而這會破壞CLR對於String類型的各種預設.此外還可能破壞CLR團隊應為String對象"不可變"而做出的各種預設.
6、CLR關於語言文化的類型一CultureInfo類和字符串與線程的關聯
7、C# 字符串操作基本過程(Equals、Compare、EndsWith等處理方法)
9、C# 高效率創建字符串類(StringBuilder).
11、C# 自定義類型通過實現IFormattable接口,來輸出指定的格式和語言文化的字符串(例:DateTime)
12、C# String.Format的格式限定符與Format方法將多個對象格式化一個字符串原理