字符串(C# 编程指南)Strings (C# Programming Guide)

字符串是值为文本的 String 类型对象。A string is an object of type String whose value is text. 文本在内部存储为 Char 对象的依序只读集合。Internally, the text is stored as a sequential read-only collection of Char objects. 在 C# 字符串末尾没有 null 终止字符;因此,一个 C# 字符串可以包含任何数量的嵌入的 null 字符 ('\0')。There is no null-terminating character at the end of a C# string; therefore a C# string can contain any number of embedded null characters ('\0'). 字符串的 Length 属性表示其包含的 Char 对象数量,而非 Unicode 字符数。The Length property of a string represents the number of Char objects it contains, not the number of Unicode characters. 若要访问字符串中的各个 Unicode 码位,请使用 StringInfo 对象。To access the individual Unicode code points in a string, use the StringInfo object.

string 与System.Stringstring vs. System.String

在 C# 中,string 关键字是 String 的别名。In C#, the string keyword is an alias for String. 因此,Stringstring 是等效的,你可以使用你所喜欢的任何一种命名约定。Therefore, String and string are equivalent, and you can use whichever naming convention you prefer. String 类提供了安全创建、操作和比较字符串的多种方法。The String class provides many methods for safely creating, manipulating, and comparing strings. 此外,C# 语言重载了部分运算符,以简化常见字符串操作。In addition, the C# language overloads some operators to simplify common string operations. 有关关键字的详细信息,请参阅 stringFor more information about the keyword, see string. 有关类型及其方法的详细信息,请参阅 StringFor more information about the type and its methods, see String.

声明和初始化字符串Declaring and Initializing Strings

可以使用各种方法声明和初始化字符串,如以下示例中所示:You can declare and initialize strings in various ways, as shown in the following example:

// Declare without initializing.
string message1;

// Initialize to null.
string message2 = null;

// Initialize as an empty string.
// Use the Empty constant instead of the literal "".
string message3 = System.String.Empty;

// Initialize with a regular string literal.
string oldPath = "c:\\Program Files\\Microsoft Visual Studio 8.0";

// Initialize with a verbatim string literal.
string newPath = @"c:\Program Files\Microsoft Visual Studio 9.0";

// Use System.String if you prefer.
System.String greeting = "Hello World!";

// In local variables (i.e. within a method body)
// you can use implicit typing.
var temp = "I'm still a strongly-typed System.String!";

// Use a const string to prevent 'message4' from
// being used to store another string value.
const string message4 = "You can't get rid of me!";

// Use the String constructor only when creating
// a string from a char*, char[], or sbyte*. See
// System.String documentation for details.
char[] letters = { 'A', 'B', 'C' };
string alphabet = new string(letters);

请注意,不要使用 new 运算符创建字符串对象,除非使用字符数组初始化字符串。Note that you do not use the new operator to create a string object except when initializing the string with an array of chars.

使用 Empty 常量值初始化字符串,以新建字符串长度为零的 String 对象。Initialize a string with the Empty constant value to create a new String object whose string is of zero length. 长度为零的字符串文本表示法是“”。The string literal representation of a zero-length string is "". 通过使用 Empty 值(而不是 null)初始化字符串,可以减少 NullReferenceException 发生的可能性。By initializing strings with the Empty value instead of null, you can reduce the chances of a NullReferenceException occurring. 尝试访问字符串前,先使用静态 IsNullOrEmpty(String) 方法验证字符串的值。Use the static IsNullOrEmpty(String) method to verify the value of a string before you try to access it.

字符串对象的不可变性Immutability of String Objects

字符串对象是“不可变的” :它们在创建后无法更改。String objects are immutable: they cannot be changed after they have been created. 看起来是在修改字符串的所有 String 方法和 C# 运算符实际上都是在新的字符串对象中返回结果。All of the String methods and C# operators that appear to modify a string actually return the results in a new string object. 在下面的示例中,当 s1s2 的内容被串联在一起以形成单个字符串时,两个原始字符串没有被修改。In the following example, when the contents of s1 and s2 are concatenated to form a single string, the two original strings are unmodified. += 运算符创建一个新的字符串,其中包含组合的内容。The += operator creates a new string that contains the combined contents. 这个新对象被分配给变量 s1,而分配给 s1 的原始对象被释放,以供垃圾回收,因为没有任何其他变量包含对它的引用。That new object is assigned to the variable s1, and the original object that was assigned to s1 is released for garbage collection because no other variable holds a reference to it.

string s1 = "A string is more ";
string s2 = "than the sum of its chars.";

// Concatenate s1 and s2. This actually creates 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 of its chars.

由于字符串“modification”实际上是一个新创建的字符串,因此,必须在创建对字符串的引用时使用警告。Because a string "modification" is actually a new string creation, you must use caution when you create references to strings. 如果创建了字符串的引用,然后“修改”了原始字符串,则该引用将继续指向原始对象,而非指向修改字符串时所创建的新对象。If you create a reference to a string, and then "modify" the original string, the reference will continue to point to the original object instead of the new object that was created when the string was modified. 以下代码阐释了此行为:The following code illustrates this behavior:

string s1 = "Hello ";
string s2 = s1;
s1 += "World";

System.Console.WriteLine(s2);
//Output: Hello

若要详细了解如何新建基于修改(如对原始字符串执行的搜索和替换操作)的字符串,请参阅如何:修改字符串内容For more information about how to create new strings that are based on modifications such as search and replace operations on the original string, see How to: Modify String Contents.

常规和逐字字符串文本Regular and Verbatim String Literals

在必须嵌入 C# 提供的转义字符时,使用常规字符串文本,如以下示例所示:Use regular string literals when you must embed escape characters provided by C#, as shown in the following example:

string columns = "Column 1\tColumn 2\tColumn 3";
//Output: Column 1        Column 2        Column 3

string rows = "Row 1\r\nRow 2\r\nRow 3";
/* Output:
  Row 1
  Row 2
  Row 3
*/

string title = "\"The \u00C6olean Harp\", by Samuel Taylor Coleridge";
//Output: "The Æolean Harp", by Samuel Taylor Coleridge

当字符串文本包含反斜杠字符(例如在文件路径中)时,出于便捷性和更强的可读性的考虑,使用逐字字符串。Use verbatim strings for convenience and better readability when the string text contains backslash characters, for example in file paths. 由于逐字字符串将新的行字符作为字符串文本的一部分保留,因此可将其用于初始化多行字符串。Because verbatim strings preserve new line characters as part of the string text, they can be used to initialize multiline strings. 使用双引号在逐字字符串内部嵌入引号。Use double quotation marks to embed a quotation mark inside a verbatim string. 下面的示例演示逐字字符串的一些常见用法:The following example shows some common uses for verbatim strings:

string filePath = @"C:\Users\scoleridge\Documents\";
//Output: C:\Users\scoleridge\Documents\

string text = @"My pensive SARA ! thy soft 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
   To sit beside our Cot,... 
*/

string quote = @"Her name was ""Sara.""";
//Output: Her name was "Sara."

字符串转义序列String Escape Sequences

转义序列Escape sequence 字符名称Character name Unicode 编码Unicode encoding
\'\' 单引号Single quote 0x00270x0027
\"\" 双引号Double quote 0x00220x0022
\\ 反斜杠Backslash 0x005C0x005C
\0\0 nullNull 0x00000x0000
\a\a 警报Alert 0x00070x0007
\b\b BackspaceBackspace 0x00080x0008
\f\f 换页Form feed 0x000C0x000C
\n\n 换行New line 0x000A0x000A
\r\r 回车Carriage return 0x000D0x000D
\t\t 水平制表符Horizontal tab 0x00090x0009
\v\v 垂直制表符Vertical tab 0x000B0x000B
\u\u Unicode 转义序列 (UTF-16)Unicode escape sequence (UTF-16) \uHHHH(范围:0000 - FFFF;示例:\u00E7 =“ç”)\uHHHH (range: 0000 - FFFF; example: \u00E7 = "ç")
\U\U Unicode 转义序列 (UTF-32)Unicode escape sequence (UTF-32) \U00HHHHHH(范围:000000 - 10FFFF;示例:\U0001F47D =“👽”)\U00HHHHHH (range: 000000 - 10FFFF; example: \U0001F47D = "👽")
\x\x 除长度可变外,Unicode 转义序列与“\u”类似Unicode escape sequence similar to "\u" except with variable length \xH[H][H][H](范围:0 - FFFF;示例:\x00E7\x0E7\xE7 =“ç”)\xH[H][H][H] (range: 0 - FFFF; example: \x00E7 or \x0E7 or \xE7 = "ç")

警告

使用 \x 转义序列且指定的位数小于 4 个十六进制数字时,如果紧跟在转义序列后面的字符是有效的十六进制数字(即 0-9、A-F 和 a-f),则这些字符将被解释为转义序列的一部分。When using the \x escape sequence and specifying less than 4 hex digits, if the characters that immediately follow the escape sequence are valid hex digits (i.e. 0-9, A-F, and a-f), they will be interpreted as being part of the escape sequence. 例如,\xA1 会生成“¡”,即码位 U+00A1。For example, \xA1 produces "¡", which is code point U+00A1. 但是,如果下一个字符是“A”或“a”,则转义序列将转而被解释为 \xA1A 并生成“ਚ”(即码位 U+0A1A)。However, if the next character is "A" or "a", then the escape sequence will instead be interpreted as being \xA1A and produce "ਚ", which is code point U+0A1A. 在此类情况下,如果指定全部 4 个十六进制数字(例如 \x00A1),则可能导致解释出错。In such cases, specifying all 4 hex digits (e.g. \x00A1 ) will prevent any possible misinterpretation.

备注

在编译时,逐字字符串被转换为普通字符串,并具有所有相同的转义序列。At compile time, verbatim strings are converted to ordinary strings with all the same escape sequences. 因此,如果在调试器监视窗口中查看逐字字符串,将看到由编译器添加的转义字符,而不是来自你的源代码的逐字字符串版本。Therefore, if you view a verbatim string in the debugger watch window, you will see the escape characters that were added by the compiler, not the verbatim version from your source code. 例如,原义字符串 @"C:\files.txt" 在监视窗口中显示为“C:\\files.txt”。For example, the verbatim string @"C:\files.txt" will appear in the watch window as "C:\\files.txt".

格式字符串Format Strings

格式字符串是在运行时以动态方式确定其内容的字符串。A format string is a string whose contents are determined dynamically at runtime. 格式字符串是通过将内插表达式 或占位符嵌入字符串大括号内创建的。Format strings are created by embedding interpolated expressions or placeholders inside of braces within a string. 大括号 ({...}) 中的所有内容都将解析为一个值,并在运行时以格式化字符串的形式输出。Everything inside the braces ({...}) will be resolved to a value and output as a formatted string at runtime. 有两种方法创建格式字符串:字符串内插和复合格式。There are two methods to create format strings: string interpolation and composite formatting.

字符串内插String Interpolation

在 C# 6.0 及更高版本中提供,内插字符串 $ 特殊字符标识,并在大括号中包含内插表达式。Available in C# 6.0 and later, interpolated strings are identified by the $ special character and include interpolated expressions in braces. 如果不熟悉字符串内插,请参阅字符串内插 - C# 交互式教程快速概览。If you are new to string interpolation, see the String interpolation - C# interactive tutorial for a quick overview.

使用字符串内插来改善代码的可读性和可维护性。Use string interpolation to improve the readability and maintainability of your code. 字符串内插可实现与 String.Format 方法相同的结果,但提高了易用性和内联清晰度。String interpolation achieves the same results as the String.Format method, but improves ease of use and inline clarity.

var jh = (firstName: "Jupiter", lastName: "Hammon", born: 1711, published: 1761);
Console.WriteLine($"{jh.firstName} {jh.lastName} was an African American poet born in {jh.born}.");
Console.WriteLine($"He was first published in {jh.published} at the age of {jh.published - jh.born}.");
Console.WriteLine($"He'd be over {Math.Round((2018d - jh.born) / 100d) * 100d} years old today.");

// Output:
// Jupiter Hammon was an African American poet born in 1711.
// He was first published in 1761 at the age of 50.
// He'd be over 300 years old today. 

复合格式设置Composite Formatting

String.Format 利用大括号中的占位符创建格式字符串。The String.Format utilizes placeholders in braces to create a format string. 此示例生成与上面使用的字符串内插方法类似的输出。This example results in similar output to the string interpolation method used above.

var pw = (firstName: "Phillis", lastName: "Wheatley", born: 1753, published: 1773);
Console.WriteLine("{0} {1} was an African American poet born in {2}.", pw.firstName, pw.lastName, pw.born);
Console.WriteLine("She was first published in {0} at the age of {1}.", pw.published, pw.published - pw.born);
Console.WriteLine("She'd be over {0} years old today.", Math.Round((2018d - pw.born) / 100d) * 100d);

// Output:
// Phillis Wheatley was an African American poet born in 1753.
// She was first published in 1773 at the age of 20.
// She'd be over 300 years old today.

有关设置 .NET 类型格式的详细信息,请参阅 .NET 中的格式设置类型For more information on formatting .NET types see Formatting Types in .NET.

子字符串Substrings

子字符串是包含在字符串中的任何字符序列。A substring is any sequence of characters that is contained in a string. 使用 Substring 方法可以通过原始字符串的一部分新建字符串。Use the Substring method to create a new string from a part of the original string. 可以使用 IndexOf 方法搜索一次或多次出现的子字符串。You can search for one or more occurrences of a substring by using the IndexOf method. 使用 Replace 方法可以将出现的所有指定子字符串替换为新字符串。Use the Replace method to replace all occurrences of a specified substring with a new string. Substring 方法一样,Replace 实际返回的是新字符串,且不修改原始字符串。Like the Substring method, Replace actually returns a new string and does not modify the original string. 有关详细信息,请参阅如何:搜索字符串如何:修改字符串内容For more information, see How to: search strings and How to: Modify String Contents.

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

可以使用包含索引值的数组表示法来获取对单个字符的只读访问权限,如下面的示例中所示:You can use array notation with an index value to acquire read-only access to individual characters, as in the following example:

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 方法存储结果。If the String methods do not provide the functionality that you must have to modify individual characters in a string, you can use a StringBuilder object to modify the individual chars "in-place", and then create a new string to store the results by using the StringBuilder methods. 在下面的示例中,假定必须以特定方式修改原始字符串,然后存储结果以供未来使用:In the following example, assume that you must modify the original string in a particular way and then store the results for future use:

string question = "hOW DOES mICROSOFT wORD DEAL WITH THE cAPS lOCK KEY?";
System.Text.StringBuilder sb = new System.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 deal with the Caps Lock key?            

Null 字符串和空字符串Null Strings and Empty Strings

空字符串是包含零个字符的 System.String 对象实例。An empty string is an instance of a System.String object that contains zero characters. 空字符串常用在各种编程方案中,表示空文本字段。Empty strings are used often in various programming scenarios to represent a blank text field. 可以对空字符串调用方法,因为它们是有效的 System.String 对象。You can call methods on empty strings because they are valid System.String objects. 对空字符串进行了初始化,如下所示:Empty strings are initialized as follows:

string s = String.Empty;  

相比较而言,null 字符串并不指 System.String 对象实例,只要尝试对 null 字符串调用方法,都会引发 NullReferenceExceptionBy contrast, a null string does not refer to an instance of a System.String object and any attempt to call a method on a null string causes a NullReferenceException. 但是,可以在串联和与其他字符串的比较操作中使用 null 字符串。However, you can use null strings in concatenation and comparison operations with other strings. 以下示例说明了对 null 字符串的引用会引发和不会引发意外的某些情况:The following examples illustrate some cases in which a reference to a null string does and does not cause an exception to be thrown:

static void Main()
{
    string str = "hello";
    string nullStr = null;
    string emptyStr = String.Empty;

    string tempStr = str + nullStr;
    // Output of the following line: hello
    Console.WriteLine(tempStr);

    bool b = (emptyStr == nullStr);
    // Output of the following line: 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";
    // Output of the following line: * abc*
    Console.WriteLine("*" + s1 + "*");
    // Output of the following line: *abc *
    Console.WriteLine("*" + s2 + "*");
    // Output of the following line: 4
    Console.WriteLine(s2.Length);
}

使用 StringBuilder 快速创建字符串Using StringBuilder for Fast String Creation

.NET 中的字符串操作进行了高度的优化,在大多数情况下不会显著影响性能。String operations in .NET are highly optimized and in most cases do not significantly impact performance. 但是,在某些情况下(例如,执行数百次或数千次的紧密循环),字符串操作可能影响性能。However, in some scenarios such as tight loops that are executing many hundreds or thousands of times, string operations can affect performance. StringBuilder 类创建字符串缓冲区,用于在程序执行多个字符串操控时提升性能。The StringBuilder class creates a string buffer that offers better performance if your program performs many string manipulations. 使用 StringBuilder 字符串,还可以重新分配各个字符,而内置字符串数据类型则不支持这样做。The StringBuilder string also enables you to reassign individual characters, something the built-in string data type does not support. 例如,此代码更改字符串的内容,而无需创建新的字符串:This code, for example, changes the content of a string without creating a new string:

System.Text.StringBuilder sb = new System.Text.StringBuilder("Rat: the ideal pet");
sb[0] = 'C';
System.Console.WriteLine(sb.ToString());
System.Console.ReadLine();

//Outputs Cat: the ideal pet

在以下示例中,StringBuilder 对象用于通过一组数字类型创建字符串:In this example, a StringBuilder object is used to create a string from a set of numeric types:

using System;
using System.Text;

namespace CSRefStrings
{
    class TestStringBuilder
    {
        static void Main()
        {
            var sb = new StringBuilder();

            // Create a string composed of numbers 0 - 9
            for (int i = 0; i < 10; i++)
            {
                sb.Append(i.ToString());
            }
            Console.WriteLine(sb);  // displays 0123456789

            // Copy one character of the string (not possible with a System.String)
            sb[0] = sb[9];

            Console.WriteLine(sb);  // displays 9123456789
            Console.WriteLine();
        }
    }
}

字符串、扩展方法和 LINQStrings, Extension Methods and LINQ

由于 String 类型实现 IEnumerable<T>,因此可以对字符串使用 Enumerable 类中定义的扩展方法。Because the String type implements IEnumerable<T>, you can use the extension methods defined in the Enumerable class on strings. 为了避免视觉干扰,这些方法已从 String 类型的 IntelliSense 中排除,但它们仍然可用。To avoid visual clutter, these methods are excluded from IntelliSense for the String type, but they are available nevertheless. 此外,还可以使用字符串上的 LINQLINQ 查询表达式。You can also use LINQLINQ query expressions on strings. 有关详细信息,请参阅 LINQ 和字符串For more information, see LINQ and Strings.

主题Topic 说明Description
如何:修改字符串内容How to: Modify String Contents 阐明转换字符串并修改字符串内容的方法。Illustrates techniques to transform strings and modify the contents of strings.
如何:比较字符串How to: Compare Strings 演示如何对字符串执行序号和特定于区域性的比较。Shows how to perform ordinal and culture specific comparisons of strings.
如何:连接多个字符串How to: Concatenate Multiple Strings 演示将多个字符串联接成一个字符串的多种方式。Demonstrates various ways to join multiple strings into one.
如何:使用 String.Split 分析字符串How to: Parse Strings Using String.Split 包含代码示例,演示了如何使用 String.Split 方法来分析字符串。Contains code examples that illustrate how to use the String.Split method to parse strings.
如何:搜索字符串How to: Search Strings 说明如何在字符串中使用搜索来搜索特定的文本或模式。Explains how to use search for specific text or patterns in strings.
如何:确定字符串是否表示数值How to: Determine Whether a String Represents a Numeric Value 演示如何安全地分析一个字符串,以查看其是否具有有效的数值。Shows how to safely parse a string to see whether it has a valid numeric value.
字符串内插String interpolation 介绍字符串内插功能,它提供了一种方便的语法来格式化字符串。Describes the string interpolation feature that provides a convenient syntax to format strings.
基本字符串操作Basic String Operations 收录了介绍如何使用 System.StringSystem.Text.StringBuilder 方法执行基本字符串操作的主题链接。Provides links to topics that use System.String and System.Text.StringBuilder methods to perform basic string operations.
分析字符串Parsing Strings 介绍如何将 .NET 基类型的字符串表示形式转换为相应类型的实例。Describes how to convert string representations of .NET base types to instances of the corresponding types.
分析 .NET 中的日期和时间字符串Parsing Date and Time Strings in .NET 展示了如何将字符串(如“01/24/2008”)转换为 System.DateTime 对象。Shows how to convert a string such as "01/24/2008" to a System.DateTime object.
比较字符串Comparing Strings 包括有关如何比较字符串的信息,并提供 C# 和 Visual Basic 中的示例。Includes information about how to compare strings and provides examples in C# and Visual Basic.
使用 StringBuilder 类Using the StringBuilder Class 介绍了如何使用 StringBuilder 类创建和修改动态字符串对象。Describes how to create and modify dynamic string objects by using the StringBuilder class.
LINQ 和字符串LINQ and Strings 提供有关如何使用 LINQ 查询来执行各种字符串操作的信息。Provides information about how to perform various string operations by using LINQ queries.
C# 编程指南C# Programming Guide 提供介绍在 C# 中编程构造的主题的链接。Provides links to topics that explain programming constructs in C#.