////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
本技術文檔來自msdn,C#開發指南中的字符串部分,該部分提供了提供的對字符串的理解相對於我們自己買的書上所講述的更加詳細,而且從原理的角度說明了字符串的使用,在中文學習書中更多的講的是如何使用字符串。通過學習該文檔,我們可以對C#中字符串有更加深刻的理解。每個部分都帶有示例代碼,更加幫助我們理解。學習C#的時候,我們總是要以面向對象類的概念去理解,包括字符,整型,浮點型等,和C,C++中不同,注意區別理解。
在我的博客中還會繼續發來自msdn中對C#相關資源的描述,覺得好的同學可以關注,另外,文中提到的參考消息,可以自己到msdn中參考學習。
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
一個字符串是一個類型爲String的對象,它的值是文本。在它的內部,這個文本是以一定序列的只讀的Char對象的集合。在C#字符串的末尾沒有結束的控制符;因此一個C#字符串可以包含任意數量的空字符(’\0’)。也就說,在C#中忽略了空字符。一個字符串的Length屬性表示它所包含的Char對象的數量,而不是Unicode字符的個數。要訪問字符串中單個Unicode代碼點,使用StringInfo對象。
string vs. System.String
在c#中,string關鍵字是String的一個別名。因此,String和string是等同的,你可以使用任意一個,根據你的喜好。String類提供了許多方法用於安全創建,操作,對比字符串。另外,c#語言重載一些操作簡化了常規的字符串操作。更多信息關於這個關鍵字的信息,參考string (C# Reference).更多關於類型和方法的信息,參考String。
Declaring and Initializing Strings
你可以用多種方式初始化聲明和初始化字符串,如下:
// Declare without initializing.
string message1;
// Initialize to null.
string message2 = null;
// Initialize as an empty string.
// Use the Empty constant instead of theliteral "".
string message3 = System.String.Empty;
//Initialize with a regular string literal.
string oldPath = "c:\\ProgramFiles\\Microsoft Visual Studio 8.0";
// Initialize with a verbatim stringliteral.
string newPath = @"c:\ProgramFiles\Microsoft Visual Studio 9.0";
// Use System.String if you prefer.
System.String greeting = "HelloWorld!";
// In local variables (i.e. within a methodbody)
// you can use implicit typing.
var temp = "I'm still a strongly-typedSystem.String!";
// Use a const string to prevent 'message4'from
// being used to store another stringvalue.
const string message4 = "You can't getrid of me!";
// Use the String constructor only whencreating
// a string from a char*, char[], orsbyte*. See
// System.String documentation for details.
char[] letters = { 'A', 'B', 'C' };
string alphabet = new string(letters);
注意,你不能使用new操作符創建字符串對象,只有當你使用char數組來初始化字符串的時候纔可以。
用Empty常量初始化一個字符串去創建一個新的String對象,它長度是0.0長度的字符串的常量表示方爲””。初始化字符串使用Empty而不是使用null,你可以減少NullReferenceException異常出現的機率。使用靜態的IsNullOrEmpty(String)取確定一個字符串的值在你視圖訪問它之前。
Immutability of String Objects(字符串對象不變性)
字符串對象是不變的:它們在已經創建之後就不能改變。所有的字符串方法和C#操作符似乎修改了字符串,但實際上是返回了一個新的字符串對象包含了修改後的內容。在下面的例子中,當s1和s2的內容合在一起之後形成一個新的單獨的字符串,而原始的字符串並沒有改變。+=操作符創建了一個新的字符串,它包含了合併的內容。新的對象分配給變量s1,原始分配給s1的對象被垃圾回收器釋放因爲沒有別的變量引用它了。
string s1 = "A string is more ";
string s2 = "than the sum of itschars.";
// Concatenate s1 and s2. This actuallycreates a new
// string object and stores it in s1,releasing the
// reference to the original object.
s1 += s2;
System.Console.WriteLine(s1);
// Output: A string is more than the sum ofits chars.
由於字符串“modification”實際上是創建的新字符串,當你創建對字符串的引用的時候你必須小心。如果你創建了對一個字符串的引用,那麼接下來對原來字符串的“修改”,這個引用將繼續指向原來的對象而不是字符串修改後創建的新的對象。下面的代碼說明這一點。
string s1 = "Hello ";
string s2 = s1;
s1 += "World";
System.Console.WriteLine(s2);
//Output: Hello
更多關於如何創基於修改原始字符串創建新字符串的信息,參考How to: Modify String Contents (C# Programming Guide).
Regular and Verbatim String Literals
當你必須要嵌入C#轉義字符時,如下:
string columns = "Column 1\tColumn2\tColumn 3";
//Output: Column 1 Column 2 Column 3
string rows = "Row 1\r\nRow 2\r\nRow3";
/* Output:
Row1
Row2
Row3
*/
string title = "\"The \u00C6oleanHarp\", by Samuel Taylor Coleridge";
//Output: "The Æolean Harp", bySamuel Taylor Coleridge
使用verbatim字符串爲了當字符串文本中包含反斜槓字符的時候更加方便和更好的閱讀性,例如,在文件路徑中。由於verbatim字符串保留了新的一行的字符作爲字符文本的一部分,它們可以用於初始化多行字符串。使用雙引號去嵌入一個引號到verbatim字符串中,下面的例子說明了verbatim字符串的一些常規的使用:
string filePath =@"C:\Users\scoleridge\Documents\";
//Output: C:\Users\scoleridge\Documents\
string text = @"My pensive SARA ! thysoft cheek reclined
Thus on mine arm, most soothing sweet it is
To sit beside our Cot,...";
/* Output:
My pensive SARA ! thy soft cheek reclined
Thus on mine arm, most soothing sweet it is
Tosit beside our Cot,...
*/
string quote = @"Her name was""Sara.""";
//Output: Her name was "Sara."
String Escape Sequences
Escape sequence |
Character name |
Unicode encoding |
\' |
Single quote |
0x0027 |
\" |
Double quote |
0x0022 |
\\ |
Backslash |
0x005C |
\0 |
Null |
0x0000 |
\a |
Alert |
0x0007 |
\b |
Backspace |
0x0008 |
\f |
Form feed |
0x000C |
\n |
New line |
0x000A |
\r |
Carriage return |
0x000D |
\t |
Horizontal tab |
0x0009 |
\U |
Unicode escape sequence for surrogate pairs. |
\Unnnnnnnn |
\u |
Unicode escape sequence |
\u0041 = "A" |
\v |
Vertical tab |
0x000B |
\x |
Unicode escape sequence similar to "\u" except with variable length. |
\x0041 = "A" |
注意:在編譯的時候,verbatim字符串會被轉換爲普通字符串通過使用相應的escape sequences(上圖中)。因此,如果你在調試器窗口中查看一個verbatim字符串,你會看到被編譯器添加的轉義字符(escape 字符),而不是你源代碼中的verbatim字符。例如,verbatim字符串@"C:\files.txt"在監視器窗口中就是"C:\\files.txt".
Format Strings
一個格式化字符串是一個字符串,它的內容在運行的時候動態的確定。你可以通過靜態的Format方法創建格式化字符串,嵌入佔位符以便在運行的時候被別的值來替換。下面的例子使用了格式化字符串循環輸出結果。
class FormatString
{
static void Main()
{
// Get user input.
System.Console.WriteLine("Enter a number");
string input = System.Console.ReadLine();
// Convert the input string to an int.
int j;
System.Int32.TryParse(input, out j);
// Write a different string each iteration.
string s;
for (int i = 0; i < 10; i++)
{
// A simple format string with no alignment formatting.
s = System.String.Format("{0} times {1} = {2}", i, j, (i *j));
System.Console.WriteLine(s);
}
//Keep the console window open in debug mode.
System.Console.ReadKey();
}
}
Substrings
字符串子集是一個字符串中包含的任意序列的字符。使用Substring方法從原始字符串的一部分創建一個新的字符串。你可以通過使用IndexOf方法搜索一個字符串子集中的一個或幾個字符。使用Replace方法用新的字符串替換指定字符串子集的字符。和Substring方法一樣,Replace方法實際上是返回一個新的字符串,而不是修改原始的字符串。更多信息,參考
How to: Search Strings Using String Methods(C# Programming Guide) and How to: Modify String Contents (C# ProgrammingGuide).
string s3 = "Visual C# Express";
System.Console.WriteLine(s3.Substring(7,2));
// Output: "C#"
System.Console.WriteLine(s3.Replace("C#","Basic"));
// Output: "Visual Basic Express"
// Index values are zero-based
int index = s3.IndexOf("C");
// index = 7
Accessing Individual Characters
你可以使用索引值通過數組標記的方式只讀式的訪問單個字符,如下:
string s5 = "Printing backwards";
for (int i = 0; i < s5.Length; i++)
{
System.Console.Write(s5[s5.Length - i - 1]);
}
// Output: "sdrawkcab gnitnirP"
如果String方法沒有提供你需要的方法去修改字符串中的單個字符,你可以使用StringBuilder對象修改單個字符,然後通過StringBuilder創建一個新的字符串存儲結果。下面的例子,假設你必須以特定的方式修改原始字符串,然後存儲結果以備後用:
string question = "hOW DOES mICROSOFTwORD DEAL WITH THE cAPS lOCK KEY?";
System.Text.StringBuilder sb = newSystem.Text.StringBuilder(question);
for (int j = 0; j < sb.Length; j++)
{
if (System.Char.IsLower(sb[j]) == true)
sb[j] = System.Char.ToUpper(sb[j]);
else if (System.Char.IsUpper(sb[j]) == true)
sb[j] = System.Char.ToLower(sb[j]);
}
// Store the new string.
string corrected = sb.ToString();
System.Console.WriteLine(corrected);
// Output: How does Microsoft Word dealwith the Caps Lock key?
Null Strings and Empty Strings
一個empty字符串是一個System.Object對象的實例,它包含了0個字符。Empty字符串在許多編程方案中使用去表示一個空白的文本字段。你可以在empty字符串上調用各種方法,因爲它們是有效的System.Object對象。Empty字符串用如下方法實例化:
string s = String.Empty;
相比之下,一個null字符串並沒有引用一個System.String對象,任何試圖在null字符串上調用方法都會引起NullReferenceException異常。然而,你可以在與的字符串比較和合並操作中使用null字符串。下面的例子說明一些例子,當中一個null字符串的引用引起異常和不引起異常的情況:
static void Main()
{
string str = "hello";
string nullStr = null;
string emptyStr = String.Empty;
string tempStr = str + nullStr;
// The following line displays "hello."
Console.WriteLine(tempStr);
bool b = (emptyStr == nullStr);
// The following line displays False.
Console.WriteLine(b);
// The following line creates a new empty string.
string newStr = emptyStr + nullStr;
// Null strings and empty strings behave differently. The following
// two lines display 0.
Console.WriteLine(emptyStr.Length);
Console.WriteLine(newStr.Length);
// The following line raises a NullReferenceException.
//Console.WriteLine(nullStr.Length);
// The null character can be displayed and counted, like other chars.
string s1 = "\x0" + "abc";
string s2 = "abc" + "\x0";
// The following line displays "* abc*".
Console.WriteLine("*" + s1 + "*");
// The following line displays "*abc *".
Console.WriteLine("*" + s2 + "*");
// The following line displays 4.
Console.WriteLine(s2.Length);
}
Using StringBuilder for Fast StringCreation
在NET中字符串的操作得到了很大的優化,在多數情況下沒有很大的影響性能。然而,在某些方案中,如循環執行幾百上千次,字符串的操作可能影響性能。類StringBuilder創建一個字符串緩衝區,如果你的程序執行許多的字符串操作,它可以爲你提供更好的性能。StringBuilder字符串改變一個字符串中的內容而不會創建新的字符串。
System.Text.StringBuilder sb = newSystem.Text.StringBuilder("Rat: the ideal pet");
sb[0] = 'C';
System.Console.WriteLine(sb.ToString());
System.Console.ReadLine();
//Outputs Cat: the ideal pet
在這個例子中,一個StringBuilder對象用於從一組數字類型創建一個字符串:
class TestStringBuilder
{
static void Main()
{
System.Text.StringBuilder sb = new System.Text.StringBuilder();
// Create a string composed of numbers 0 - 9
for (int i = 0; i < 10; i++)
{
sb.Append(i.ToString());
}
System.Console.WriteLine(sb); //displays 0123456789
// Copy one character of the string (not possible with a System.String)
sb[0] = sb[9];
System.Console.WriteLine(sb); //displays 9123456789
}
}
Strings, Extension Methods and LINQ
由於String類型實現了IEnumerable <(Of <(T >)>)接口,你可以在字符串上使用在Enumerable類中定義的擴展方法。爲了避免視覺混亂,這些方法沒有在String類型的方法中從IntelliSense(就是我們用調號訪問對象的方法的時候,彈出的可選方法列表)中排除,但是它們仍然可以使用。你也可以使用LINQ在字符串上詢問表達式。更多信息,參考LINQ and Strings