////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
本技术文档来自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