String 類別
定義
重要
部分資訊涉及發行前產品,在發行之前可能會有大幅修改。 Microsoft 對此處提供的資訊,不做任何明確或隱含的瑕疵擔保。
以一連串的 UTF-16 字碼單位表示文字。
public ref class System::String sealed : IComparable, IComparable<System::String ^>, IConvertible, IEquatable<System::String ^>, System::Collections::Generic::IEnumerable<char>
public ref class System::String sealed : ICloneable, IComparable, IComparable<System::String ^>, IConvertible, IEquatable<System::String ^>, System::Collections::Generic::IEnumerable<char>
public ref class System::String sealed : ICloneable, IComparable, IComparable<System::String ^>, IConvertible, IEquatable<System::String ^>, IParsable<System::String ^>, ISpanParsable<System::String ^>, System::Collections::Generic::IEnumerable<char>
public ref class System::String sealed : ICloneable, IComparable, IConvertible, System::Collections::IEnumerable
public ref class System::String sealed : IComparable, IComparable<System::String ^>, IEquatable<System::String ^>, System::Collections::IEnumerable
public ref class System::String sealed : IComparable, IComparable<System::String ^>, IEquatable<System::String ^>, System::Collections::Generic::IEnumerable<char>
public sealed class String : IComparable, IComparable<string>, IConvertible, IEquatable<string>, System.Collections.Generic.IEnumerable<char>
public sealed class String : ICloneable, IComparable, IComparable<string>, IConvertible, IEquatable<string>, System.Collections.Generic.IEnumerable<char>
public sealed class String : ICloneable, IComparable, IComparable<string>, IConvertible, IEquatable<string>, IParsable<string>, ISpanParsable<string>, System.Collections.Generic.IEnumerable<char>
[System.Serializable]
public sealed class String : ICloneable, IComparable, IConvertible, System.Collections.IEnumerable
[System.Serializable]
[System.Runtime.InteropServices.ComVisible(true)]
public sealed class String : ICloneable, IComparable, IComparable<string>, IConvertible, IEquatable<string>, System.Collections.Generic.IEnumerable<char>
public sealed class String : IComparable, IComparable<string>, IEquatable<string>, System.Collections.IEnumerable
public sealed class String : IComparable, IComparable<string>, IEquatable<string>, System.Collections.Generic.IEnumerable<char>
type string = class
interface seq<char>
interface IEnumerable
interface IComparable
interface IComparable<string>
interface IConvertible
interface IEquatable<string>
type string = class
interface seq<char>
interface IEnumerable
interface ICloneable
interface IComparable
interface IComparable<string>
interface IConvertible
interface IEquatable<string>
type string = class
interface seq<char>
interface IEnumerable
interface ICloneable
interface IComparable
interface IComparable<string>
interface IConvertible
interface IEquatable<string>
interface IParsable<string>
interface ISpanParsable<string>
type string = class
interface seq<char>
interface IEnumerable
interface IComparable
interface IComparable<string>
interface IConvertible
interface IEquatable<string>
interface ICloneable
[<System.Serializable>]
type string = class
interface IComparable
interface ICloneable
interface IConvertible
interface IEnumerable
[<System.Serializable>]
[<System.Runtime.InteropServices.ComVisible(true)>]
type string = class
interface IComparable
interface ICloneable
interface IConvertible
interface IComparable<string>
interface seq<char>
interface IEnumerable
interface IEquatable<string>
[<System.Serializable>]
[<System.Runtime.InteropServices.ComVisible(true)>]
type string = class
interface IComparable
interface ICloneable
interface IConvertible
interface IEnumerable
interface IComparable<string>
interface seq<char>
interface IEquatable<string>
type string = class
interface IEnumerable
interface IComparable
interface IComparable<string>
interface IEquatable<string>
type string = class
interface IComparable
interface IComparable<string>
interface IEquatable<string>
interface seq<char>
interface IEnumerable
Public NotInheritable Class String
Implements IComparable, IComparable(Of String), IConvertible, IEnumerable(Of Char), IEquatable(Of String)
Public NotInheritable Class String
Implements ICloneable, IComparable, IComparable(Of String), IConvertible, IEnumerable(Of Char), IEquatable(Of String)
Public NotInheritable Class String
Implements ICloneable, IComparable, IComparable(Of String), IConvertible, IEnumerable(Of Char), IEquatable(Of String), IParsable(Of String), ISpanParsable(Of String)
Public NotInheritable Class String
Implements ICloneable, IComparable, IConvertible, IEnumerable
Public NotInheritable Class String
Implements IComparable, IComparable(Of String), IEnumerable, IEquatable(Of String)
Public NotInheritable Class String
Implements IComparable, IComparable(Of String), IEnumerable(Of Char), IEquatable(Of String)
- 繼承
-
String
- 屬性
- 實作
備註
字串是用來表示文字之字元的循序集合。 String物件是代表字串之 System.Char 物件的循序集合; System.Char 物件會對應至 UTF-16 程式碼單位。 物件的值 String 是物件循序集合 System.Char 的內容,而該值是固定的 (,也就是唯讀) 。 如需字串不變性的詳細資訊,請參閱 Immutability 和 StringBuilder 類別 一節。 記憶體中物件的大小 String 上限為 2 GB,或大約 10 億個字元。
如需 Unicode、UTF-16、程式碼單位、字碼點和 Char 類型 Rune 的詳細資訊,請參閱 .NET 中的字元編碼簡介。
本節內容:
具現化 String 物件
Char 物件和 Unicode 字元
字串和 Unicode 標準
字串和內嵌的 Null 字元
字串和索引
Null 字串和空字串
不變性和 StringBuilder 類別
序數與區分文化特性的作業
正規化
依類別排序的字串作業
具現化 String 物件
您可以透過下列方式具 String 現化 物件:
將字串常值指派給 String 變數。 這是最常用來建立字串的方法。 下列範例會使用指派來建立數個字串。 請注意,在 C# 和 F# 中,因為反斜線 (\) 是逸出字元,所以字串中的常值反斜線必須逸出,或者整個字串必須是 @-quoted。
using namespace System; void main() { String^ string1 = "This is a string created by assignment."; Console::WriteLine(string1); String^ string2a = "The path is C:\\PublicDocuments\\Report1.doc"; Console::WriteLine(string2a); } // The example displays the following output: // This is a string created by assignment. // The path is C:\PublicDocuments\Report1.doc
string string1 = "This is a string created by assignment."; Console.WriteLine(string1); string string2a = "The path is C:\\PublicDocuments\\Report1.doc"; Console.WriteLine(string2a); string string2b = @"The path is C:\PublicDocuments\Report1.doc"; Console.WriteLine(string2b); // The example displays the following output: // This is a string created by assignment. // The path is C:\PublicDocuments\Report1.doc // The path is C:\PublicDocuments\Report1.doc
let string1 = "This is a string created by assignment." printfn "%s" string1 let string2a = "The path is C:\\PublicDocuments\\Report1.doc" printfn "%s" string2a let string2b = @"The path is C:\PublicDocuments\Report1.doc" printfn "%s" string2b // The example displays the following output: // This is a string created by assignment. // The path is C:\PublicDocuments\Report1.doc // The path is C:\PublicDocuments\Report1.doc
Dim string1 As String = "This is a string created by assignment." Console.WriteLine(string1) Dim string2 As String = "The path is C:\PublicDocuments\Report1.doc" Console.WriteLine(string2) ' The example displays the following output: ' This is a string created by assignment. ' The path is C:\PublicDocuments\Report1.doc
藉由呼叫 String 類別建構函式。 下列範例會呼叫數個類別建構函式來具現化字串。 請注意,某些建構函式包含字元陣列的指標或帶正負號的位元組陣列做為參數。 Visual Basic 不支援呼叫這些建構函式。 如需建構函式的詳細資訊 String ,請參閱建 String 構函式摘要。
using namespace System; void main() { wchar_t chars[5] = L"word"; char bytes[6] = { 0x41, 0x42, 0x43, 0x44, 0x45, 0x00 }; // Create a string from a character array. String^ string1 = gcnew String(chars); Console::WriteLine(string1); // Create a string that consists of a character repeated 20 times. String^ string2 = gcnew String('c', 20); Console::WriteLine(string2); String^ stringFromBytes = nullptr; String^ stringFromChars = nullptr; char * pbytes = &bytes[0]; // Create a string from a pointer to a signed byte array. stringFromBytes = gcnew String(pbytes); wchar_t* pchars = &chars[0]; // Create a string from a pointer to a character array. stringFromChars = gcnew String(pchars); Console::WriteLine(stringFromBytes); Console::WriteLine(stringFromChars); Console::ReadLine(); } // The example displays the following output: // word // cccccccccccccccccccc // ABCDE // word
char[] chars = { 'w', 'o', 'r', 'd' }; sbyte[] bytes = { 0x41, 0x42, 0x43, 0x44, 0x45, 0x00 }; // Create a string from a character array. string string1 = new string(chars); Console.WriteLine(string1); // Create a string that consists of a character repeated 20 times. string string2 = new string('c', 20); Console.WriteLine(string2); string stringFromBytes = null; string stringFromChars = null; unsafe { fixed (sbyte* pbytes = bytes) { // Create a string from a pointer to a signed byte array. stringFromBytes = new string(pbytes); } fixed (char* pchars = chars) { // Create a string from a pointer to a character array. stringFromChars = new string(pchars); } } Console.WriteLine(stringFromBytes); Console.WriteLine(stringFromChars); // The example displays the following output: // word // cccccccccccccccccccc // ABCDE // word
let chars = [| 'w'; 'o'; 'r'; 'd' |] let bytes = [| 0x41y; 0x42y; 0x43y; 0x44y; 0x45y; 0x00y |] // Create a string from a character array. let string1 = String chars printfn "%s" string1 // Create a string that consists of a character repeated 20 times. let string2 = String('c', 20) printfn "%s" string2 let stringFromBytes = // Create a string from a pointer to a signed byte array. use pbytes = fixed bytes String pbytes let stringFromChars = // Create a string from a pointer to a character array. use pchars = fixed chars String pchars printfn $"{stringFromBytes}" printfn $"{stringFromChars}" // The example displays the following output: // word // cccccccccccccccccccc // ABCDE // word
Dim chars() As Char = { "w"c, "o"c, "r"c, "d"c } ' Create a string from a character array. Dim string1 As New String(chars) Console.WriteLine(string1) ' Create a string that consists of a character repeated 20 times. Dim string2 As New String("c"c, 20) Console.WriteLine(string2) ' The example displays the following output: ' word ' cccccccccccccccccccc
使用 C# 和 F# 中的字串串連運算子 (+,以及 & Visual Basic 中的 或 +) ,從實例和字串常值的任何組合 String 建立單一字串。 下列範例說明如何使用字串串連運算子。
String^ string1 = "Today is " + DateTime::Now.ToString("D") + "."; Console::WriteLine(string1); String^ string2 = "This is one sentence. " + "This is a second. "; string2 += "This is a third sentence."; Console::WriteLine(string2); // The example displays output like the following: // Today is Tuesday, July 06, 2011. // This is one sentence. This is a second. This is a third sentence.
string string1 = "Today is " + DateTime.Now.ToString("D") + "."; Console.WriteLine(string1); string string2 = "This is one sentence. " + "This is a second. "; string2 += "This is a third sentence."; Console.WriteLine(string2); // The example displays output like the following: // Today is Tuesday, July 06, 2011. // This is one sentence. This is a second. This is a third sentence.
let string1 = "Today is " + DateTime.Now.ToString("D") + "." printfn $"{string1}" let string2 = "This is one sentence. " + "This is a second. " let string2 = string2 + "This is a third sentence." printfn $"{string2}" // The example displays output like the following: // Today is Tuesday, July 06, 2011. // This is one sentence. This is a second. This is a third sentence.
Dim string1 As String = "Today is " + Date.Now.ToString("D") + "." Console.WriteLine(string1) Dim string2 As String = "This is one sentence. " + "This is a second. " string2 += "This is a third sentence." Console.WriteLine(string2) ' The example displays output like the following: ' Today is Tuesday, July 06, 2011. ' This is one sentence. This is a second. This is a third sentence.
藉由擷取屬性或呼叫傳回字串的方法。 下列範例會使用 類別的 String 方法,從較大的字串擷取子字串。
String^ sentence = "This sentence has five words."; // Extract the second word. int startPosition = sentence->IndexOf(" ") + 1; String^ word2 = sentence->Substring(startPosition, sentence->IndexOf(" ", startPosition) - startPosition); Console::WriteLine("Second word: " + word2);
string sentence = "This sentence has five words."; // Extract the second word. int startPosition = sentence.IndexOf(" ") + 1; string word2 = sentence.Substring(startPosition, sentence.IndexOf(" ", startPosition) - startPosition); Console.WriteLine("Second word: " + word2); // The example displays the following output: // Second word: sentence
let sentence = "This sentence has five words." // Extract the second word. let startPosition = sentence.IndexOf " " + 1 let word2 = sentence.Substring(startPosition, sentence.IndexOf(" ", startPosition) - startPosition) printfn $"Second word: {word2}" // The example displays the following output: // Second word: sentence
Dim sentence As String = "This sentence has five words." ' Extract the second word. Dim startPosition As Integer = sentence.IndexOf(" ") + 1 Dim word2 As String = sentence.Substring(startPosition, sentence.IndexOf(" ", startPosition) - startPosition) Console.WriteLine("Second word: " + word2) ' The example displays the following output: ' Second word: sentence
藉由呼叫格式化方法,將值或物件轉換成其字串表示。 下列範例會使用 複合格式 設定功能,將兩個 物件的字串表示內嵌至字串中。
DateTime^ dateAndTime = gcnew DateTime(2011, 7, 6, 7, 32, 0); Double temperature = 68.3; String^ result = String::Format("At {0:t} on {0:D}, the temperature was {1:F1} degrees Fahrenheit.", dateAndTime, temperature); Console::WriteLine(result); // The example displays the following output: // At 7:32 AM on Wednesday, July 06, 2011, the temperature was 68.3 degrees Fahrenheit.
DateTime dateAndTime = new DateTime(2011, 7, 6, 7, 32, 0); double temperature = 68.3; string result = String.Format("At {0:t} on {0:D}, the temperature was {1:F1} degrees Fahrenheit.", dateAndTime, temperature); Console.WriteLine(result); // The example displays the following output: // At 7:32 AM on Wednesday, July 06, 2011, the temperature was 68.3 degrees Fahrenheit.
let dateAndTime = DateTime(2011, 7, 6, 7, 32, 0) let temperature = 68.3 String.Format("At {0:t} on {0:D}, the temperature was {1:F1} degrees Fahrenheit.", dateAndTime, temperature) |> printfn "%s" // The example displays the following output: // At 7:32 AM on Wednesday, July 06, 2011, the temperature was 68.3 degrees Fahrenheit.
Dim dateAndTime As DateTime = #07/06/2011 7:32:00AM# Dim temperature As Double = 68.3 Dim result As String = String.Format("At {0:t} on {0:D}, the temperature was {1:F1} degrees Fahrenheit.", dateAndTime, temperature) Console.WriteLine(result) ' The example displays the following output: ' At 7:32 AM on Wednesday, July 06, 2011, the temperature was 68.3 degrees Fahrenheit.
Char 物件和 Unicode 字元
字串中的每個字元都是由 Unicode 純量值定義,也稱為 Unicode 字碼指標或序數 (Unicode 字元的數值) 值。 每個代碼點都會使用 UTF-16 編碼進行編碼,而編碼的每個元素的數值則以 Char 物件表示。
注意
請注意,因為 String 實例是由 UTF-16 程式碼單位的循序集合所組成,所以可以建立 String 不是格式正確的 Unicode 字串的物件。 例如,可以建立具有低 Surrogate 且沒有對應高 Surrogate 的字串。 雖然某些方法,例如命名空間中的 System.Text 編碼和解碼物件方法,可能會執行檢查以確保字串格式正確, String 類別成員不會確保字串格式正確。
單 Char 一物件通常代表單一代碼點,也就是 的 Char 數值等於代碼點。 例如,字元 「a」 的代碼點是 U+0061。 不過,程式碼點可能需要一個以上的編碼專案 (一個 Char 以上的物件) 。 Unicode 標準會定義兩種類型的字元,這些字元對應至多個 Char 物件:graphemes,以及對應至 Unicode 補充平面中字元的 Unicode 補充字碼點。
grapheme 是以基底字元,後面接著一或多個結合字元來表示。 例如,字元 ä 是由 Char 代碼點為 U+0061,後面接著 Char 代碼點為 U+0308 的物件來表示。 此字元也可以由具有 U+00E4 字碼點的單 Char 一物件定義。 如下列範例所示,相等的文化特性比較表示這兩個標記法相等,雖然一般序數比較並不相同。 不過,如果兩個字串正規化,序數比較也會指出它們相等。 (如需正規化字串的詳細資訊,請參閱 正規化 一節。)
using namespace System; using namespace System::Globalization; using namespace System::IO; void main() { StreamWriter^ sw = gcnew StreamWriter(".\\graphemes.txt"); String^ grapheme = L"a" + L"\u0308"; sw->WriteLine(grapheme); String^ singleChar = "\u00e4"; sw->WriteLine(singleChar); sw->WriteLine("{0} = {1} (Culture-sensitive): {2}", grapheme, singleChar, String::Equals(grapheme, singleChar, StringComparison::CurrentCulture)); sw->WriteLine("{0} = {1} (Ordinal): {2}", grapheme, singleChar, String::Equals(grapheme, singleChar, StringComparison::Ordinal)); sw->WriteLine("{0} = {1} (Normalized Ordinal): {2}", grapheme, singleChar, String::Equals(grapheme->Normalize(), singleChar->Normalize(), StringComparison::Ordinal)); sw->Close(); } // The example produces the following output: // ä // ä // ä = ä (Culture-sensitive): True // ä = ä (Ordinal): False // ä = ä (Normalized Ordinal): True
using System; using System.Globalization; using System.IO; public class Example { public static void Main() { StreamWriter sw = new StreamWriter(@".\graphemes.txt"); string grapheme = "\u0061\u0308"; sw.WriteLine(grapheme); string singleChar = "\u00e4"; sw.WriteLine(singleChar); sw.WriteLine("{0} = {1} (Culture-sensitive): {2}", grapheme, singleChar, String.Equals(grapheme, singleChar, StringComparison.CurrentCulture)); sw.WriteLine("{0} = {1} (Ordinal): {2}", grapheme, singleChar, String.Equals(grapheme, singleChar, StringComparison.Ordinal)); sw.WriteLine("{0} = {1} (Normalized Ordinal): {2}", grapheme, singleChar, String.Equals(grapheme.Normalize(), singleChar.Normalize(), StringComparison.Ordinal)); sw.Close(); } } // The example produces the following output: // ä // ä // ä = ä (Culture-sensitive): True // ä = ä (Ordinal): False // ä = ä (Normalized Ordinal): True
open System open System.IO do use sw = new StreamWriter(@".\graphemes.txt") let grapheme = "\u0061\u0308" sw.WriteLine grapheme let singleChar = "\u00e4" sw.WriteLine singleChar sw.WriteLine("{0} = {1} (Culture-sensitive): {2}", grapheme, singleChar, String.Equals(grapheme, singleChar, StringComparison.CurrentCulture)) sw.WriteLine("{0} = {1} (Ordinal): {2}", grapheme, singleChar, String.Equals(grapheme, singleChar, StringComparison.Ordinal)) sw.WriteLine("{0} = {1} (Normalized Ordinal): {2}", grapheme, singleChar, String.Equals(grapheme.Normalize(), singleChar.Normalize(), StringComparison.Ordinal)) // The example produces the following output: // ä // ä // ä = ä (Culture-sensitive): True // ä = ä (Ordinal): False // ä = ä (Normalized Ordinal): True
Imports System.Globalization Imports System.IO Module Example Public Sub Main() Dim sw As New StreamWriter(".\graphemes.txt") Dim grapheme As String = ChrW(&H0061) + ChrW(&h0308) sw.WriteLine(grapheme) Dim singleChar As String = ChrW(&h00e4) sw.WriteLine(singleChar) sw.WriteLine("{0} = {1} (Culture-sensitive): {2}", grapheme, singleChar, String.Equals(grapheme, singleChar, StringComparison.CurrentCulture)) sw.WriteLine("{0} = {1} (Ordinal): {2}", grapheme, singleChar, String.Equals(grapheme, singleChar, StringComparison.Ordinal)) sw.WriteLine("{0} = {1} (Normalized Ordinal): {2}", grapheme, singleChar, String.Equals(grapheme.Normalize(), singleChar.Normalize(), StringComparison.Ordinal)) sw.Close() End Sub End Module ' The example produces the following output: ' ä ' ä ' ä = ä (Culture-sensitive): True ' ä = ä (Ordinal): False ' ä = ä (Normalized Ordinal): True
) 代理字組 (Unicode 增補字碼指標是由 Char 代碼點為高 Surrogate 的物件所表示,後面接著 Char 程式碼點為低 Surrogate 的物件。 高代理程式碼單位的範圍從 U+D800 到 U+DBFF。 低代理的程式碼單位範圍從 U+DC00 到 U+DFFF。 Surrogate 字組可用來代表 16 個 Unicode 增補平面中的字元。 下列範例會建立 Surrogate 字元,並將其傳遞至 Char.IsSurrogatePair(Char, Char) 方法,以判斷它是否為 Surrogate 字組。
using namespace System; void main() { String^ surrogate = L"\xD800\xDC03" ; for (int ctr = 0; ctr < surrogate->Length; ctr++) Console::Write("U+{0:X4} ", Convert::ToUInt16(surrogate[ctr])); Console::WriteLine(); Console::WriteLine(" Is Surrogate Pair: {0}", Char::IsSurrogatePair(surrogate[0], surrogate[1])); Console::ReadLine(); } // The example displays the following output: // U+D800 U+DC03 // Is Surrogate Pair: True
string surrogate = "\uD800\uDC03"; for (int ctr = 0; ctr < surrogate.Length; ctr++) Console.Write($"U+{(ushort)surrogate[ctr]:X2} "); Console.WriteLine(); Console.WriteLine(" Is Surrogate Pair: {0}", Char.IsSurrogatePair(surrogate[0], surrogate[1])); // The example displays the following output: // U+D800 U+DC03 // Is Surrogate Pair: True
open System let surrogate = "\uD800\uDC03" for i = 0 to surrogate.Length - 1 do printf $"U+{uint16 surrogate[i]:X2} " printfn $"\n Is Surrogate Pair: {Char.IsSurrogatePair(surrogate[0], surrogate[1])}" // The example displays the following output: // U+D800 U+DC03 // Is Surrogate Pair: True
Module Example Public Sub Main() Dim surrogate As String = ChrW(&hD800) + ChrW(&hDC03) For ctr As Integer = 0 To surrogate.Length - 1 Console.Write("U+{0:X2} ", Convert.ToUInt16(surrogate(ctr))) Next Console.WriteLine() Console.WriteLine(" Is Surrogate Pair: {0}", Char.IsSurrogatePair(surrogate(0), surrogate(1))) End Sub End Module ' The example displays the following output: ' U+D800 U+DC03 ' Is Surrogate Pair: True
字串和 Unicode 標準
字串中的字元會以對應至 Char 值的 UTF-16 編碼程式碼單位來表示。
字串中的每個字元都有相關聯的 Unicode 字元類別目錄,此類別目錄是由 UnicodeCategory 列舉以 .NET 表示。 您可以呼叫 方法來判斷字元或 Surrogate 字組的 CharUnicodeInfo.GetUnicodeCategory 類別。
.NET 會維護自己的字元表及其對應的分類,以確保在不同平台上執行的特定 .NET 實作,都能傳回一致的字元類別資訊。 在所有 .NET 版本和所有作業系統平臺上,字元類別資訊是由 Unicode 字元資料庫提供。
下表列出 .NET 版本及其字元分類依據的 Unicode 標準版本。
.NET 版本 | Unicode Standard 版本 |
---|---|
.NET Framework 1.1 | Unicode Standard 4.0.0 版 |
.NET Framework 2.0 | Unicode Standard 5.0.0 版 |
.NET Framework 3.5 | Unicode Standard 5.0.0 版 |
.NET Framework 4 | Unicode Standard 5.0.0 版 |
.NET Framework 4.5 | Unicode Standard 6.3.0 版 |
.NET Framework 4.5.1 | Unicode Standard 6.3.0 版 |
.NET Framework 4.5.2 | Unicode Standard 6.3.0 版 |
.NET Framework 4.6 | Unicode Standard 6.3.0 版 |
.NET Framework 4.6.1 | Unicode Standard 6.3.0 版 |
.NET framework 4.6.2 及更新版本 | Unicode Standard 8.0.0 版 |
.NET Core 2.1 | Unicode Standard 8.0.0 版 |
.NET Core 3.1 | Unicode Standard 11.0.0 版 |
.NET 5 | Unicode Standard 13.0.0 版 |
此外,.NET 也支援以 Unicode 標準為基礎的字串比較和排序。 .NET Framework 4 和舊版會維護自己的字串資料資料表。 從 Windows 7 上執行的 .NET Framework 4.5 開始,這也適用于 .NET Framework 版本。 從在 Windows 8 和更新版本的 Windows 作業系統上執行的 .NET Framework 4.5 開始,執行時間會將字串比較和排序作業委派給作業系統。 在 .NET Core 和 .NET 5+ 上,除了 Windows 10 2019 年 5 月更新) 之前的 Windows 版本以外,Unicode 連結 (庫國際元件會提供字串比較和排序資訊。 下表列出 .NET 的版本,以及字元比較和排序依據的 Unicode Standard 版本。
.NET 版本 | Unicode Standard 版本 |
---|---|
.NET Framework 1.1 | Unicode Standard 4.0.0 版 |
.NET Framework 2.0 | Unicode Standard 5.0.0 版 |
.NET Framework 3.5 | Unicode Standard 5.0.0 版 |
.NET Framework 4 | Unicode Standard 5.0.0 版 |
Windows 7 上的 .NET Framework 4.5 及更新版本 | Unicode Standard 5.0.0 版 |
在 Windows 8 和更新版本的 Windows 作業系統上.NET Framework 4.5 和更新版本 | Unicode Standard 6.3.0 版 |
.NET Core 和 .NET 5+ | 取決於基礎作業系統所支援的 Unicode Standard 版本。 |
字串和內嵌的 Null 字元
在 .NET 中 String ,物件可以包含內嵌的 Null 字元,此字元會算為字串長度的一部分。 不過,在某些語言中,例如 C 和 C++,Null 字元表示字串結尾;它不會被視為字串的一部分,而且不會計入字串長度的一部分。 這表示在 C 或 C++ 中撰寫的 C 和 C++ 程式設計人員或程式庫在套用至 String 物件時不一定有效,下列常見假設:
或
wcslen
函式所strlen
傳回的值不一定等於 String.Length 。或
wcscpy_s
函式所建立的strcpy_s
字串不一定與 方法所建立的 String.Copy 字串相同。
您應該確保具現化 String 物件的原生 C 和 C++ 程式碼,以及透過平台叫用傳遞 String 物件的程式碼,請勿假設內嵌的 Null 字元會標示字串的結尾。
當字串排序 (或比較) 字串時,以及在搜尋字串時,也會以不同的方式處理字串中的內嵌 Null 字元。 在兩個字串之間執行區分文化特性的比較時,會忽略 Null 字元,包括使用不因文化特性而異的比較。 它們只會被視為序數或不區分大小寫的序數比較。 另一方面,使用 、 StartsWith 和 IndexOf 等 Contains 方法搜尋字串時,一律會考慮內嵌的 Null 字元。
字串和索引
索引是 物件的位置, (不是 中的 String Unicode 字元) 。 Char 索引是以零起始的非負數,從字串中的第一個位置開始,也就是索引位置零。 許多搜尋方法,例如 IndexOf 和 LastIndexOf ,會傳回字串實例中字元或子字串的索引。
屬性 Chars[] 可讓您依字串中的索引位置來存取個別 Char 物件。 由於 屬性 Chars[] 是 Visual Basic) 中的預設屬性 (,或 C# 和 F#) 中的索引子 (,因此您可以使用下列程式碼來存取字串中的個別 Char 物件。 此程式碼會尋找字串中的空白字元或標點符號字元,以判斷字串包含的字數。
using namespace System;
void main()
{
String^ s1 = "This string consists of a single short sentence.";
int nWords = 0;
s1 = s1->Trim();
for (int ctr = 0; ctr < s1->Length; ctr++) {
if (Char::IsPunctuation(s1[ctr]) | Char::IsWhiteSpace(s1[ctr]))
nWords++;
}
Console::WriteLine("The sentence\n {0}\nhas {1} words.",
s1, nWords);
}
// The example displays the following output:
// The sentence
// This string consists of a single short sentence.
// has 8 words.
string s1 = "This string consists of a single short sentence.";
int nWords = 0;
s1 = s1.Trim();
for (int ctr = 0; ctr < s1.Length; ctr++) {
if (Char.IsPunctuation(s1[ctr]) | Char.IsWhiteSpace(s1[ctr]))
nWords++;
}
Console.WriteLine("The sentence\n {0}\nhas {1} words.",
s1, nWords);
// The example displays the following output:
// The sentence
// This string consists of a single short sentence.
// has 8 words.
let s1 = "This string consists of a single short sentence."
let mutable nWords = 0
for i = 0 to s1.Length - 1 do
if Char.IsPunctuation s1[i] || Char.IsWhiteSpace s1[i] then
nWords <- nWords + 1
printfn $"The sentence\n {s1}\nhas {nWords} words."
// The example displays the following output:
// The sentence
// This string consists of a single short sentence.
// has 8 words.
Module Example
Public Sub Main()
Dim s1 As String = "This string consists of a single short sentence."
Dim nWords As Integer = 0
s1 = s1.Trim()
For ctr As Integer = 0 To s1.Length - 1
If Char.IsPunctuation(s1(ctr)) Or Char.IsWhiteSpace(s1(ctr))
nWords += 1
End If
Next
Console.WriteLine("The sentence{2} {0}{2}has {1} words.",
s1, nWords, vbCrLf)
End Sub
End Module
' The example displays the following output:
' The sentence
' This string consists of a single short sentence.
' has 8 words.
String由於 類別會實作 IEnumerable 介面,因此您也可以使用 建構逐一 foreach
查看 Char 字串中的 物件,如下列範例所示。
using namespace System;
void main()
{
String^ s1 = "This string consists of a single short sentence.";
int nWords = 0;
s1 = s1->Trim();
for each (Char ch in s1)
{
if (Char::IsPunctuation(ch) | Char::IsWhiteSpace(ch))
nWords++;
}
Console::WriteLine("The sentence\n {0}\nhas {1} words.",
s1, nWords);
Console::ReadLine();
}
// The example displays the following output:
// The sentence
// This string consists of a single short sentence.
// has 8 words.
string s1 = "This string consists of a single short sentence.";
int nWords = 0;
s1 = s1.Trim();
foreach (var ch in s1) {
if (Char.IsPunctuation(ch) | Char.IsWhiteSpace(ch))
nWords++;
}
Console.WriteLine("The sentence\n {0}\nhas {1} words.",
s1, nWords);
// The example displays the following output:
// The sentence
// This string consists of a single short sentence.
// has 8 words.
let s1 = "This string consists of a single short sentence."
let mutable nWords = 0
for ch in s1 do
if Char.IsPunctuation ch || Char.IsWhiteSpace ch then
nWords <- nWords + 1
printfn $"The sentence\n {s1}\nhas {nWords} words."
// The example displays the following output:
// The sentence
// This string consists of a single short sentence.
// has 8 words.
Module Example
Public Sub Main()
Dim s1 As String = "This string consists of a single short sentence."
Dim nWords As Integer = 0
s1 = s1.Trim()
For Each ch In s1
If Char.IsPunctuation(ch) Or Char.IsWhiteSpace(ch) Then
nWords += 1
End If
Next
Console.WriteLine("The sentence{2} {0}{2}has {1} words.",
s1, nWords, vbCrLf)
End Sub
End Module
' The example displays the following output:
' The sentence
' This string consists of a single short sentence.
' has 8 words.
連續索引值可能不會對應到連續 Unicode 字元,因為 Unicode 字元可能會編碼為多個 Char 物件。 特別是,字串可能包含由基底字元所構成的多重字元單位,後面接著一或多個結合字元或 Surrogate 配對。 若要使用 Unicode 字元,而不是 Char 物件,請使用 System.Globalization.StringInfo 和 TextElementEnumerator 類別,或 String.EnumerateRunes 方法和 Rune 結構。 下列範例說明與物件搭配 Char 使用的程式碼與使用 Unicode 字元的程式碼之間的差異。 它會比較句子中每個單字中的字元或文字元素數目。 字串包含兩個基底字元序列,後面接著結合字元。
using namespace System;
using namespace System::Collections::Generic;
using namespace System::Globalization;
void main()
{
// First sentence of The Mystery of the Yellow Room, by Leroux.
String^ opening = L"Ce n'est pas sans une certaine émotion que "+
L"je commence à raconter ici les aventures " +
L"extraordinaires de Joseph Rouletabille.";
// Character counters.
int nChars = 0;
// Objects to store word count.
List<int>^ chars = gcnew List<int>();
List<int>^ elements = gcnew List<int>();
for each (Char ch in opening) {
// Skip the ' character.
if (ch == '\x0027') continue;
if (Char::IsWhiteSpace(ch) | (Char::IsPunctuation(ch))) {
chars->Add(nChars);
nChars = 0;
}
else {
nChars++;
}
}
TextElementEnumerator^ te = StringInfo::GetTextElementEnumerator(opening);
while (te->MoveNext()) {
String^ s = te->GetTextElement();
// Skip the ' character.
if (s == "\x0027") continue;
if ( String::IsNullOrEmpty(s->Trim()) | (s->Length == 1 && Char::IsPunctuation(Convert::ToChar(s)))) {
elements->Add(nChars);
nChars = 0;
}
else {
nChars++;
}
}
// Display character counts.
Console::WriteLine("{0,6} {1,20} {2,20}",
"Word #", "Char Objects", "Characters");
for (int ctr = 0; ctr < chars->Count; ctr++)
Console::WriteLine("{0,6} {1,20} {2,20}",
ctr, chars[ctr], elements[ctr]);
Console::ReadLine();
}
// The example displays the following output:
// Word # Char Objects Characters
// 0 2 2
// 1 4 4
// 2 3 3
// 3 4 4
// 4 3 3
// 5 8 8
// 6 8 7
// 7 3 3
// 8 2 2
// 9 8 8
// 10 2 1
// 11 8 8
// 12 3 3
// 13 3 3
// 14 9 9
// 15 15 15
// 16 2 2
// 17 6 6
// 18 12 12
// First sentence of The Mystery of the Yellow Room, by Leroux.
string opening = "Ce n'est pas sans une certaine émotion que "+
"je commence à raconter ici les aventures " +
"extraordinaires de Joseph Rouletabille.";
// Character counters.
int nChars = 0;
// Objects to store word count.
List<int> chars = new List<int>();
List<int> elements = new List<int>();
foreach (var ch in opening) {
// Skip the ' character.
if (ch == '\u0027') continue;
if (Char.IsWhiteSpace(ch) | (Char.IsPunctuation(ch))) {
chars.Add(nChars);
nChars = 0;
}
else {
nChars++;
}
}
System.Globalization.TextElementEnumerator te =
System.Globalization.StringInfo.GetTextElementEnumerator(opening);
while (te.MoveNext()) {
string s = te.GetTextElement();
// Skip the ' character.
if (s == "\u0027") continue;
if ( String.IsNullOrEmpty(s.Trim()) | (s.Length == 1 && Char.IsPunctuation(Convert.ToChar(s)))) {
elements.Add(nChars);
nChars = 0;
}
else {
nChars++;
}
}
// Display character counts.
Console.WriteLine("{0,6} {1,20} {2,20}",
"Word #", "Char Objects", "Characters");
for (int ctr = 0; ctr < chars.Count; ctr++)
Console.WriteLine("{0,6} {1,20} {2,20}",
ctr, chars[ctr], elements[ctr]);
// The example displays the following output:
// Word # Char Objects Characters
// 0 2 2
// 1 4 4
// 2 3 3
// 3 4 4
// 4 3 3
// 5 8 8
// 6 8 7
// 7 3 3
// 8 2 2
// 9 8 8
// 10 2 1
// 11 8 8
// 12 3 3
// 13 3 3
// 14 9 9
// 15 15 15
// 16 2 2
// 17 6 6
// 18 12 12
open System
open System.Globalization
// First sentence of The Mystery of the Yellow Room, by Leroux.
let opening = "Ce n'est pas sans une certaine émotion que je commence à raconter ici les aventures extraordinaires de Joseph Rouletabille."
// Character counters.
let mutable nChars = 0
// Objects to store word count.
let chars = ResizeArray<int>()
let elements = ResizeArray<int>()
for ch in opening do
// Skip the ' character.
if ch <> '\u0027' then
if Char.IsWhiteSpace ch || Char.IsPunctuation ch then
chars.Add nChars
nChars <- 0
else
nChars <- nChars + 1
let te = StringInfo.GetTextElementEnumerator opening
while te.MoveNext() do
let s = te.GetTextElement()
// Skip the ' character.
if s <> "\u0027" then
if String.IsNullOrEmpty(s.Trim()) || (s.Length = 1 && Char.IsPunctuation(Convert.ToChar s)) then
elements.Add nChars
nChars <- 0
else
nChars <- nChars + 1
// Display character counts.
printfn "%6s %20s %20s" "Word #" "Char Objects " "Characters"
for i = 0 to chars.Count - 1 do
printfn "%6d %20d %20d" i chars[i] elements[i]
// The example displays the following output:
// Word # Char Objects Characters
// 0 2 2
// 1 4 4
// 2 3 3
// 3 4 4
// 4 3 3
// 5 8 8
// 6 8 7
// 7 3 3
// 8 2 2
// 9 8 8
// 10 2 1
// 11 8 8
// 12 3 3
// 13 3 3
// 14 9 9
// 15 15 15
// 16 2 2
// 17 6 6
// 18 12 12
Imports System.Collections.Generic
Imports System.Globalization
Module Example
Public Sub Main()
' First sentence of The Mystery of the Yellow Room, by Leroux.
Dim opening As String = "Ce n'est pas sans une certaine émotion que "+
"je commence à raconter ici les aventures " +
"extraordinaires de Joseph Rouletabille."
' Character counters.
Dim nChars As Integer = 0
' Objects to store word count.
Dim chars As New List(Of Integer)()
Dim elements As New List(Of Integer)()
For Each ch In opening
' Skip the ' character.
If ch = ChrW(&h0027) Then Continue For
If Char.IsWhiteSpace(ch) Or Char.IsPunctuation(ch) Then
chars.Add(nChars)
nChars = 0
Else
nChars += 1
End If
Next
Dim te As TextElementEnumerator = StringInfo.GetTextElementEnumerator(opening)
Do While te.MoveNext()
Dim s As String = te.GetTextElement()
' Skip the ' character.
If s = ChrW(&h0027) Then Continue Do
If String.IsNullOrEmpty(s.Trim()) Or (s.Length = 1 AndAlso Char.IsPunctuation(Convert.ToChar(s)))
elements.Add(nChars)
nChars = 0
Else
nChars += 1
End If
Loop
' Display character counts.
Console.WriteLine("{0,6} {1,20} {2,20}",
"Word #", "Char Objects", "Characters")
For ctr As Integer = 0 To chars.Count - 1
Console.WriteLine("{0,6} {1,20} {2,20}",
ctr, chars(ctr), elements(ctr))
Next
End Sub
End Module
' The example displays the following output:
' Word # Char Objects Characters
' 0 2 2
' 1 4 4
' 2 3 3
' 3 4 4
' 4 3 3
' 5 8 8
' 6 8 7
' 7 3 3
' 8 2 2
' 9 8 8
' 10 2 1
' 11 8 8
' 12 3 3
' 13 3 3
' 14 9 9
' 15 15 15
' 16 2 2
' 17 6 6
' 18 12 12
此範例使用 StringInfo.GetTextElementEnumerator 方法和 TextElementEnumerator 類別來列舉字串中的所有文字元素,來搭配文字元素使用。 您也可以藉由呼叫 StringInfo.ParseCombiningCharacters 方法來擷取包含每個文字專案的起始索引的陣列。
如需使用文字單位而非個別 Char 值的詳細資訊,請參閱 .NET 中的字元編碼簡介。
Null 字串和空字串
已宣告但尚未指派值的字串為 null
。 嘗試在該字串上呼叫方法會 NullReferenceException 擲回 。 Null 字串與空字串不同,這是值為 「」 或 String.Empty 的字串。 在某些情況下,將 Null 字串或空字串當做方法呼叫中的引數傳遞會擲回例外狀況。 例如,將 Null 字串傳遞至 方法會擲回 Int32.Parse ,而傳遞空字串會擲回 FormatException 。 ArgumentNullException 在其他情況下,方法引數可以是 Null 字串或空字串。 例如,如果您要提供 IFormattable 類別的實作,則想要將 null 字串和空字串與一般 (「G」) 格式規範相等。
類別 String 包含下列兩種便利方法,可讓您測試字串是否為 null
或空白:
IsNullOrEmpty,表示字串是否為
null
或 等於 String.Empty 。 此方法不需要使用下列程式碼:if (str == nullptr || str->Equals(String::Empty))
if (str == null || str.Equals(String.Empty))
if str = null || str.Equals String.Empty then
If str Is Nothing OrElse str.Equals(String.Empty) Then
IsNullOrWhiteSpace,表示字串是否為
null
、等於 String.Empty ,或 是由空白字元獨佔所組成。 此方法不需要使用下列程式碼:if (str == nullptr || str->Equals(String::Empty) || str->Trim()->Equals(String::Empty))
if (str == null || str.Equals(String.Empty) || str.Trim().Equals(String.Empty))
if str = null || str.Equals String.Empty || str.Trim().Equals String.Empty then
If str Is Nothing OrElse str.Equals(String.Empty) OrElse str.Trim().Equals(String.Empty)
下列範例會在 IsNullOrEmpty 自訂 Temperature
類別的實作中使用 IFormattable.ToString 方法。 方法支援 「G」、「C」、「F」 和 「K」 格式字串。 如果空格式字串或其值 null
傳遞至 方法的格式字串,其值會變更為 「G」 格式字串。
public:
virtual String^ ToString(String^ format, IFormatProvider^ provider)
{
if (String::IsNullOrEmpty(format)) format = "G";
if (provider == nullptr) provider = CultureInfo::CurrentCulture;
switch (Convert::ToUInt16(format->ToUpperInvariant()))
{
// Return degrees in Celsius.
case 'G':
case 'C':
return temp.ToString("F2", provider) + L"�C";
// Return degrees in Fahrenheit.
case 'F':
return (temp * 9 / 5 + 32).ToString("F2", provider) + L"�F";
// Return degrees in Kelvin.
case 'K':
return (temp + 273.15).ToString();
default:
throw gcnew FormatException(
String::Format("The {0} format string is not supported.",
format));
}
}
public string ToString(string format, IFormatProvider provider)
{
if (String.IsNullOrEmpty(format)) format = "G";
if (provider == null) provider = CultureInfo.CurrentCulture;
switch (format.ToUpperInvariant())
{
// Return degrees in Celsius.
case "G":
case "C":
return temp.ToString("F2", provider) + "°C";
// Return degrees in Fahrenheit.
case "F":
return (temp * 9 / 5 + 32).ToString("F2", provider) + "°F";
// Return degrees in Kelvin.
case "K":
return (temp + 273.15).ToString();
default:
throw new FormatException(
String.Format("The {0} format string is not supported.",
format));
}
}
member _.ToString(format: string, provider: IFormatProvider) =
let format =
if String.IsNullOrEmpty format then "G" else format
let provider: IFormatProvider =
if provider = null then CultureInfo.CurrentCulture else provider
match format.ToUpperInvariant() with
// Return degrees in Celsius.
| "G"
| "C" ->
temp.ToString("F2", provider) + "°C"
// Return degrees in Fahrenheit.
| "F" ->
(temp * 9. / 5. + 32.).ToString("F2", provider) + "°F"
// Return degrees in Kelvin.
| "K" ->
(temp + 273.15).ToString()
| _ ->
raise (FormatException(String.Format("The {0} format string is not supported.",format)))
Public Overloads Function ToString(fmt As String, provider As IFormatProvider) As String _
Implements IFormattable.ToString
If String.IsNullOrEmpty(fmt) Then fmt = "G"
If provider Is Nothing Then provider = CultureInfo.CurrentCulture
Select Case fmt.ToUpperInvariant()
' Return degrees in Celsius.
Case "G", "C"
Return temp.ToString("F2", provider) + "°C"
' Return degrees in Fahrenheit.
Case "F"
Return (temp * 9 / 5 + 32).ToString("F2", provider) + "°F"
' Return degrees in Kelvin.
Case "K"
Return (temp + 273.15).ToString()
Case Else
Throw New FormatException(
String.Format("The {0} format string is not supported.",
fmt))
End Select
End Function
不變性和 StringBuilder 類別
String物件稱為不可變 (唯讀) ,因為它的值在建立之後無法修改。 似乎修改 String 物件的方法實際上會傳回包含修改的新 String 物件。
因為字串是不可變的,所以對單一字串執行重複新增或刪除的字串操作常式可能會造成顯著的效能負面影響。 例如,下列程式碼會使用亂數字產生器,在範圍中建立 1000 個字元的字串,0x0001 0x052F。 雖然程式碼似乎使用字串串連,將新字元附加至名為 str
的現有字串,但它實際上會為每個串連作業建立新的 String 物件。
using namespace System;
using namespace System::IO;
using namespace System::Text;
void main()
{
Random^ rnd = gcnew Random();
String^ str = String::Empty;
StreamWriter^ sw = gcnew StreamWriter(".\\StringFile.txt",
false, Encoding::Unicode);
for (int ctr = 0; ctr <= 1000; ctr++) {
str += Convert::ToChar(rnd->Next(1, 0x0530));
if (str->Length % 60 == 0)
str += Environment::NewLine;
}
sw->Write(str);
sw->Close();
}
using System;
using System.IO;
using System.Text;
public class Example
{
public static void Main()
{
Random rnd = new Random();
string str = String.Empty;
StreamWriter sw = new StreamWriter(@".\StringFile.txt",
false, Encoding.Unicode);
for (int ctr = 0; ctr <= 1000; ctr++) {
str += (char)rnd.Next(1, 0x0530);
if (str.Length % 60 == 0)
str += Environment.NewLine;
}
sw.Write(str);
sw.Close();
}
}
open System
open System.IO
open System.Text
do
let rnd = Random()
let mutable str = String.Empty
use sw = new StreamWriter(@".\StringFile.txt", false, Encoding.Unicode)
for _ = 0 to 1000 do
str <- str + (rnd.Next(1, 0x0530) |> char |> string)
if str.Length % 60 = 0 then
str <- str + Environment.NewLine
sw.Write str
Imports System.IO
Imports System.Text
Module Example
Public Sub Main()
Dim rnd As New Random()
Dim str As String = String.Empty
Dim sw As New StreamWriter(".\StringFile.txt",
False, Encoding.Unicode)
For ctr As Integer = 0 To 1000
str += ChrW(rnd.Next(1, &h0530))
If str.Length Mod 60 = 0 Then str += vbCrLf
Next
sw.Write(str)
sw.Close()
End Sub
End Module
您可以針對對字串值進行多個變更的作業使用 StringBuilder 類別,而不是 String 類別。 不同于 類別的 String 實例, StringBuilder 物件是可變動的;當您從字串串連、附加或刪除子字串時,作業會在單一字串上執行。 當您完成修改 物件的值 StringBuilder 時,您可以呼叫其 方法,將它 StringBuilder.ToString 轉換成字串。 下列範例會取代上一個範例中使用的 , String 將範圍中的 1000 個隨機字串連,以0x0001以 物件0x052F StringBuilder 。
using namespace System;
using namespace System::IO;
using namespace System::Text;
void main()
{
Random^ rnd = gcnew Random();
StringBuilder^ sb = gcnew StringBuilder();
StreamWriter^ sw = gcnew StreamWriter(".\\StringFile.txt",
false, Encoding::Unicode);
for (int ctr = 0; ctr <= 1000; ctr++) {
sb->Append(Convert::ToChar(rnd->Next(1, 0x0530)));
if (sb->Length % 60 == 0)
sb->AppendLine();
}
sw->Write(sb->ToString());
sw->Close();
}
using System;
using System.IO;
using System.Text;
public class Example
{
public static void Main()
{
Random rnd = new Random();
StringBuilder sb = new StringBuilder();
StreamWriter sw = new StreamWriter(@".\StringFile.txt",
false, Encoding.Unicode);
for (int ctr = 0; ctr <= 1000; ctr++) {
sb.Append((char)rnd.Next(1, 0x0530));
if (sb.Length % 60 == 0)
sb.AppendLine();
}
sw.Write(sb.ToString());
sw.Close();
}
}
open System
open System.IO
open System.Text
do
let rnd = Random()
let sb = StringBuilder()
use sw = new StreamWriter(@".\StringFile.txt", false, Encoding.Unicode)
for _ = 0 to 1000 do
sb.Append(rnd.Next(1, 0x0530) |> char) |> ignore
if sb.Length % 60 = 0 then
sb.AppendLine() |> ignore
sw.Write(string sb)
Imports System.IO
Imports System.Text
Module Example
Public Sub Main()
Dim rnd As New Random()
Dim sb As New StringBuilder()
Dim sw As New StreamWriter(".\StringFile.txt",
False, Encoding.Unicode)
For ctr As Integer = 0 To 1000
sb.Append(ChrW(rnd.Next(1, &h0530)))
If sb.Length Mod 60 = 0 Then sb.AppendLine()
Next
sw.Write(sb.ToString())
sw.Close()
End Sub
End Module
序數與區分文化特性的作業
類別的成員 String 會在 物件上 String 執行序數或區分文化特性 (語言) 作業。 序數運算會處理每個 Char 物件的數值。 區分文化特性的 String 作業會處理物件的值,並將特定文化特性的大小寫、排序、格式設定和剖析規則納入考慮。 區分文化特性的作業會在明確宣告的文化特性或隱含目前文化特性的內容中執行。 這兩種作業在相同的字串上執行時,可能會產生非常不同的結果。
.NET 也支援不區分文化特性的語言字串作業,方法是使用非變異文化特性 (CultureInfo.InvariantCulture) ,其根據與區域無關的英文文化特性設定鬆散。 System.Globalization.CultureInfo與其他設定不同,不可變文化特性的設定保證在單一電腦上、從系統到系統,以及跨 .NET 版本保持一致。 不可變的文化特性可以視為一種黑色方塊,可確保所有文化特性的字串比較和排序穩定性。
重要
如果您的應用程式針對檔案名或具名管道等符號識別碼,或 XML 檔案中的文字型資料之類的保存資料做出安全性決策,則作業應該使用序數比較,而不是區分文化特性的比較。 這是因為區分文化特性的比較可能會根據作用中的文化特性產生不同的結果,而序數比較只取決於比較字元的二進位值。
重要
執行字串作業的大部分方法都包含具有 型 StringComparison 別參數的多載,可讓您指定方法是否執行序數或區分文化特性的作業。 一般而言,您應該呼叫此多載,以清除方法呼叫的意圖。 如需在字串上使用序數和區分文化特性作業的最佳做法和指引,請參閱 使用字串的最佳做法。
大小寫、剖析和格式設定、比較和排序,以及測試是否相等的作業可以是序數或區分文化特性。 下列各節將討論每個作業類別。
提示
您應該一律呼叫方法多載,以便清除方法呼叫的意圖。 例如,您應該使用目前文化特性的慣例呼叫 方法,而不是 Compare(String, String) 呼叫 方法,以對兩個字串執行區分文化特性的比較,而是應該使用 引數的值 StringComparison.CurrentCulturecomparisonType
呼叫 Compare(String, String, StringComparison) 方法。 如需詳細資訊,請參閱使用字串的最佳做法。
您可以從下列連結下載排序權數資料表,這是一組文字檔,其中包含排序和比較作業中所用字元權數的資訊:
- Windows (.NET Framework 和 .NET Core) :排序權數資料表
- Windows 10 2019 年 5 月更新或更新版本 (.NET 5+) 和 Linux 和 macOS (.NET Core 和 .NET 5+) :預設 Unicode 定序元素資料表
大小寫
大小寫規則決定如何變更 Unicode 字元的大小寫;例如,從小寫到大寫。 通常,大小寫作業會在字串比較之前執行。 例如,字串可能會轉換成大寫,以便與另一個大寫字串進行比較。 您可以藉由呼叫 ToLower 或 ToLowerInvariant 方法,將字串中的字元轉換成小寫,而且您可以呼叫 ToUpper 或 ToUpperInvariant 方法將它們轉換成大寫。 此外,您可以使用 方法, TextInfo.ToTitleCase 將字串轉換成標題大小寫。
注意
只在 Linux 和 macOS 系統上執行的 .NET Core: C 和 Posix 文化特性的定序行為一律會區分大小寫,因為這些文化特性不會使用預期的 Unicode 定序順序。 建議您使用 C 或 Posix 以外的文化特性來執行區分文化特性、不區分大小寫的排序作業。
大小寫作業可以根據目前文化特性的規則、指定的文化特性或不變異的文化特性。 因為案例對應可能會因使用的文化特性而有所不同,所以大小寫作業的結果可能會根據文化特性而有所不同。 大小寫的實際差異有三種:
拉丁大寫字母 I (U+0049) 、LATIN SMALL LETTER I (U+0069) 、拉丁大寫字母 I WITH DOT ABOVE (U+0130) 和 LATIN SMALL LETTER DOTLESS I (U+0131) 的案例對應差異。 在 tr-TR (土耳其文 (土耳其文) ) 和 az-Latn-AZ (亞塞塞亞、拉丁) 文化特性,以及在 tr、az 和 az-Latn 中性文化特性中,對等的拉丁大寫字母 I 是 LATIN SMALL LETTER DOTLESS I,而 LATIN SMALL LETTER I 的大寫對等專案則是上方的拉丁大寫大寫字母 I WITH DOT ABOVE。 在其他所有文化特性中,包括非變異文化特性、LATIN SMALL LETTER I 和 LATIN CAPITAL LETTER I 都是小寫和大寫對等專案。
下列範例示範如何設計來防止檔案系統存取的字串比較在依賴區分文化特性的大小寫比較時失敗。 (應該已使用非變異文化特性的大小寫慣例。)
using System; using System.Globalization; using System.Threading; public class Example { const string disallowed = "file"; public static void Main() { IsAccessAllowed(@"FILE:\\\c:\users\user001\documents\FinancialInfo.txt"); } private static void IsAccessAllowed(String resource) { CultureInfo[] cultures = { CultureInfo.CreateSpecificCulture("en-US"), CultureInfo.CreateSpecificCulture("tr-TR") }; String scheme = null; int index = resource.IndexOfAny( new Char[] { '\\', '/' } ); if (index > 0) scheme = resource.Substring(0, index - 1); // Change the current culture and perform the comparison. foreach (var culture in cultures) { Thread.CurrentThread.CurrentCulture = culture; Console.WriteLine("Culture: {0}", CultureInfo.CurrentCulture.DisplayName); Console.WriteLine(resource); Console.WriteLine("Access allowed: {0}", ! String.Equals(disallowed, scheme, StringComparison.CurrentCultureIgnoreCase)); Console.WriteLine(); } } } // The example displays the following output: // Culture: English (United States) // FILE:\\\c:\users\user001\documents\FinancialInfo.txt // Access allowed: False // // Culture: Turkish (Turkey) // FILE:\\\c:\users\user001\documents\FinancialInfo.txt // Access allowed: True
open System open System.Globalization open System.Threading let disallowed = "file" let isAccessAllowed (resource: string) = let cultures = [| CultureInfo.CreateSpecificCulture "en-US" CultureInfo.CreateSpecificCulture "tr-TR" |] let index = resource.IndexOfAny [| '\\'; '/' |] let scheme = if index > 0 then resource.Substring(0, index - 1) else null // Change the current culture and perform the comparison. for culture in cultures do Thread.CurrentThread.CurrentCulture <- culture printfn $"Culture: {CultureInfo.CurrentCulture.DisplayName}" printfn $"{resource}" printfn $"Access allowed: {String.Equals(disallowed, scheme, StringComparison.CurrentCultureIgnoreCase) |> not}" printfn "" isAccessAllowed @"FILE:\\\c:\users\user001\documents\FinancialInfo.txt" // The example displays the following output: // Culture: English (United States) // FILE:\\\c:\users\user001\documents\FinancialInfo.txt // Access allowed: False // // Culture: Turkish (Turkey) // FILE:\\\c:\users\user001\documents\FinancialInfo.txt // Access allowed: True
Imports System.Globalization Imports System.Threading Module Example Const disallowed = "file" Public Sub Main() IsAccessAllowed("FILE:\\\c:\users\user001\documents\FinancialInfo.txt") End Sub Private Sub IsAccessAllowed(resource As String) Dim cultures() As CultureInfo = { CultureInfo.CreateSpecificCulture("en-US"), CultureInfo.CreateSpecificCulture("tr-TR") } Dim scheme As String = Nothing Dim index As Integer = resource.IndexOfAny( {"\"c, "/"c }) If index > 0 Then scheme = resource.Substring(0, index - 1) ' Change the current culture and perform the comparison. For Each culture In cultures Thread.CurrentThread.CurrentCulture = culture Console.WriteLine("Culture: {0}", CultureInfo.CurrentCulture.DisplayName) Console.WriteLine(resource) Console.WriteLine("Access allowed: {0}", Not String.Equals(disallowed, scheme, StringComparison.CurrentCultureIgnoreCase)) Console.WriteLine() Next End Sub End Module ' The example displays the following output: ' Culture: English (United States) ' FILE:\\\c:\users\user001\documents\FinancialInfo.txt ' Access allowed: False ' ' Culture: Turkish (Turkey) ' FILE:\\\c:\users\user001\documents\FinancialInfo.txt ' Access allowed: True
不可變文化特性與所有其他文化特性之間的對應差異。 在這些情況下,使用不變異文化特性的大小寫規則,將字元變更為大寫或小寫會傳回相同的字元。 對於所有其他文化特性,它會傳回不同的字元。 下表列出部分受影響的字元。
字元 如果已變更為 傳回 (U+00B5) 大寫 希臘大寫字母 MU (U+-39C) 英文大寫字母 I,具有上方的點 (U+0130) 小寫 拉丁小寫字母 I (U+0069) 拉丁小字母虛線 I (U+0131) 大寫 拉丁大寫字母 I (U+0049) 拉丁小寫字母 LONG S (U+017F) 大寫 拉丁大寫字母 S (U+0053) 具有 CARON (U+01C5 小寫字母 Z 的拉丁大寫字母 D) 小寫 具有 CARON (U+01C6 的拉丁小寫字母) 結合希臘文 YPOGEGRAMMENI (U+0345) 大寫 希臘大寫字母 IOTA (U+0399) ASCII 字元範圍中兩個字母混合大小寫組的案例對應差異。 在大部分的文化特性中,雙字母混合大小寫組等於相等的兩個字母大寫或小寫組。 這不適用於下列文化特性中的下列兩個字母組,因為在每個案例中,它們都會與聽寫進行比較:
hr-HR (克羅埃西亞 (克羅埃西亞文) ) 文化特性中的 「lJ」 和 「nJ」。
cs-CZ (捷克文 (捷克文) ) 和 sk-SK (塞爾維亞 (文) ) 文化特性中的 「cH」。
da-DK (丹麥文 (丹麥文) ) 文化特性中的 「aA」。
hu-HU (匈牙利文 (匈牙利文) ) 文化特性中的 「cS」、「dZS」、「dZS」、「nY」、「sZ」、「tY」 和 「zS」。
es-ES_tradnl (西班牙文 (西班牙、傳統排序) ) 文化特性中的 「cH」 和 「lL」。
vi-VN (越南文 (越南) ) 文化特性中的 「cH」、「gI」、「kH」、「nH」、「nH」、「pH」、「qU'、」tH「 和 」tR」。
不過,發生區分文化特性比較這些配對會造成問題的情況不尋常,因為這些配對在固定字串或識別碼中並不常見。
下列範例說明將字串轉換成大寫時,文化特性之間大小寫規則的一些差異。
using namespace System;
using namespace System::Globalization;
using namespace System::IO;
String^ ShowHexValue(String^ s);
void main()
{
StreamWriter^ sw = gcnew StreamWriter(".\\case.txt");
array<String^>^ words = gcnew array<String^> { L"file", L"sıfır", L"Dženana" };
array<CultureInfo^>^ cultures = gcnew array<CultureInfo^> { CultureInfo::InvariantCulture,
gcnew CultureInfo("en-US"),
gcnew CultureInfo("tr-TR") };
for each (String^ word in words) {
sw->WriteLine("{0}:", word);
for each (CultureInfo^ culture in cultures) {
String^ name = String::IsNullOrEmpty(culture->Name) ?
"Invariant" : culture->Name;
String^ upperWord = word->ToUpper(culture);
sw->WriteLine(" {0,10}: {1,7} {2, 38}", name,
upperWord, ShowHexValue(upperWord));
}
sw->WriteLine();
}
sw->Close();
}
String^ ShowHexValue(String^ s)
{
String^ retval = nullptr;
for each (Char ch in s) {
array<Byte>^ bytes = BitConverter::GetBytes(ch);
retval += String::Format("{0:X2} {1:X2} ", bytes[1], bytes[0]);
}
return retval;
}
// The example displays the following output:
// file:
// Invariant: FILE 00 46 00 49 00 4C 00 45
// en-US: FILE 00 46 00 49 00 4C 00 45
// tr-TR: FİLE 00 46 01 30 00 4C 00 45
//
// sıfır:
// Invariant: SıFıR 00 53 01 31 00 46 01 31 00 52
// en-US: SIFIR 00 53 00 49 00 46 00 49 00 52
// tr-TR: SIFIR 00 53 00 49 00 46 00 49 00 52
//
// Dženana:
// Invariant: DžENANA 01 C5 00 45 00 4E 00 41 00 4E 00 41
// en-US: DŽENANA 01 C4 00 45 00 4E 00 41 00 4E 00 41
// tr-TR: DŽENANA 01 C4 00 45 00 4E 00 41 00 4E 00 41
using System;
using System.Globalization;
using System.IO;
public class Example
{
public static void Main()
{
StreamWriter sw = new StreamWriter(@".\case.txt");
string[] words = { "file", "sıfır", "Dženana" };
CultureInfo[] cultures = { CultureInfo.InvariantCulture,
new CultureInfo("en-US"),
new CultureInfo("tr-TR") };
foreach (var word in words) {
sw.WriteLine("{0}:", word);
foreach (var culture in cultures) {
string name = String.IsNullOrEmpty(culture.Name) ?
"Invariant" : culture.Name;
string upperWord = word.ToUpper(culture);
sw.WriteLine(" {0,10}: {1,7} {2, 38}", name,
upperWord, ShowHexValue(upperWord));
}
sw.WriteLine();
}
sw.Close();
}
private static string ShowHexValue(string s)
{
string retval = null;
foreach (var ch in s) {
byte[] bytes = BitConverter.GetBytes(ch);
retval += String.Format("{0:X2} {1:X2} ", bytes[1], bytes[0]);
}
return retval;
}
}
// The example displays the following output:
// file:
// Invariant: FILE 00 46 00 49 00 4C 00 45
// en-US: FILE 00 46 00 49 00 4C 00 45
// tr-TR: FİLE 00 46 01 30 00 4C 00 45
//
// sıfır:
// Invariant: SıFıR 00 53 01 31 00 46 01 31 00 52
// en-US: SIFIR 00 53 00 49 00 46 00 49 00 52
// tr-TR: SIFIR 00 53 00 49 00 46 00 49 00 52
//
// Dženana:
// Invariant: DžENANA 01 C5 00 45 00 4E 00 41 00 4E 00 41
// en-US: DŽENANA 01 C4 00 45 00 4E 00 41 00 4E 00 41
// tr-TR: DŽENANA 01 C4 00 45 00 4E 00 41 00 4E 00 41
open System
open System.Globalization
open System.IO
let showHexValue (s: string) =
let mutable retval = ""
for ch in s do
let bytes = BitConverter.GetBytes ch
retval <- retval + String.Format("{0:X2} {1:X2} ", bytes[1], bytes[0])
retval
do
use sw = new StreamWriter(@".\case.txt")
let words = [| "file"; "sıfır"; "Dženana" |]
let cultures =
[| CultureInfo.InvariantCulture
CultureInfo "en-US"
CultureInfo "tr-TR" |]
for word in words do
sw.WriteLine("{0}:", word)
for culture in cultures do
let name =
if String.IsNullOrEmpty culture.Name then "Invariant" else culture.Name
let upperWord = word.ToUpper culture
sw.WriteLine(" {0,10}: {1,7} {2, 38}", name, upperWord, showHexValue upperWord)
sw.WriteLine()
sw.Close()
// The example displays the following output:
// file:
// Invariant: FILE 00 46 00 49 00 4C 00 45
// en-US: FILE 00 46 00 49 00 4C 00 45
// tr-TR: FİLE 00 46 01 30 00 4C 00 45
//
// sıfır:
// Invariant: SıFıR 00 53 01 31 00 46 01 31 00 52
// en-US: SIFIR 00 53 00 49 00 46 00 49 00 52
// tr-TR: SIFIR 00 53 00 49 00 46 00 49 00 52
//
// Dženana:
// Invariant: DžENANA 01 C5 00 45 00 4E 00 41 00 4E 00 41
// en-US: DŽENANA 01 C4 00 45 00 4E 00 41 00 4E 00 41
// tr-TR: DŽENANA 01 C4 00 45 00 4E 00 41 00 4E 00 41
Imports System.Globalization
Imports System.IO
Module Example
Public Sub Main()
Dim sw As New StreamWriter(".\case.txt")
Dim words As String() = { "file", "sıfır", "Dženana" }
Dim cultures() As CultureInfo = { CultureInfo.InvariantCulture,
New CultureInfo("en-US"),
New CultureInfo("tr-TR") }
For Each word In words
sw.WriteLine("{0}:", word)
For Each culture In cultures
Dim name As String = If(String.IsNullOrEmpty(culture.Name),
"Invariant", culture.Name)
Dim upperWord As String = word.ToUpper(culture)
sw.WriteLine(" {0,10}: {1,7} {2, 38}", name,
upperWord, ShowHexValue(upperWord))
Next
sw.WriteLine()
Next
sw.Close()
End Sub
Private Function ShowHexValue(s As String) As String
Dim retval As String = Nothing
For Each ch In s
Dim bytes() As Byte = BitConverter.GetBytes(ch)
retval += String.Format("{0:X2} {1:X2} ", bytes(1), bytes(0))
Next
Return retval
End Function
End Module
' The example displays the following output:
' file:
' Invariant: FILE 00 46 00 49 00 4C 00 45
' en-US: FILE 00 46 00 49 00 4C 00 45
' tr-TR: FİLE 00 46 01 30 00 4C 00 45
'
' sıfır:
' Invariant: SıFıR 00 53 01 31 00 46 01 31 00 52
' en-US: SIFIR 00 53 00 49 00 46 00 49 00 52
' tr-TR: SIFIR 00 53 00 49 00 46 00 49 00 52
'
' Dženana:
' Invariant: DžENANA 01 C5 00 45 00 4E 00 41 00 4E 00 41
' en-US: DŽENANA 01 C4 00 45 00 4E 00 41 00 4E 00 41
' tr-TR: DŽENANA 01 C4 00 45 00 4E 00 41 00 4E 00 41
剖析和格式化
格式化和剖析是反向作業。 格式化規則會決定如何將日期與時間或數位等值轉換成其字串標記法,而剖析規則則決定如何將字串表示轉換為日期和時間等值。 格式化和剖析規則都取決於文化慣例。 下列範例說明解譯特定文化特性日期字串時可能發生的模棱兩可。 若不知道用來產生日期字串的文化特性慣例,就無法知道 2011 年 1 月 3 日、2011 年 3 月 1 日、2011 年 3 月 1 日和 2011 年 1 月 3 日或 2011 年 3 月 1 日。
using namespace System;
using namespace System::Globalization;
void main()
{
DateTime^ date = gcnew DateTime(2011, 3, 1);
array<CultureInfo^>^ cultures = gcnew array<CultureInfo^> { CultureInfo::InvariantCulture,
gcnew CultureInfo("en-US"),
gcnew CultureInfo("fr-FR") };
for each (CultureInfo^ culture in cultures)
Console::WriteLine("{0,-12} {1}", String::IsNullOrEmpty(culture->Name) ?
"Invariant" : culture->Name,
date->ToString("d", culture));
}
// The example displays the following output:
// Invariant 03/01/2011
// en-US 3/1/2011
// fr-FR 01/03/2011
using System;
using System.Globalization;
public class Example
{
public static void Main()
{
DateTime date = new DateTime(2011, 3, 1);
CultureInfo[] cultures = { CultureInfo.InvariantCulture,
new CultureInfo("en-US"),
new CultureInfo("fr-FR") };
foreach (var culture in cultures)
Console.WriteLine("{0,-12} {1}", String.IsNullOrEmpty(culture.Name) ?
"Invariant" : culture.Name,
date.ToString("d", culture));
}
}
// The example displays the following output:
// Invariant 03/01/2011
// en-US 3/1/2011
// fr-FR 01/03/2011
open System
open System.Globalization
let date = DateTime(2011, 3, 1)
let cultures =
[| CultureInfo.InvariantCulture
CultureInfo "en-US"
CultureInfo "fr-FR" |]
for culture in cultures do
printfn $"""{(if String.IsNullOrEmpty culture.Name then "Invariant" else culture.Name),-12} {date.ToString("d", culture)}"""
// The example displays the following output:
// Invariant 03/01/2011
// en-US 3/1/2011
// fr-FR 01/03/2011
Imports System.Globalization
Module Example
Public Sub Main()
Dim dat As Date = #3/1/2011#
Dim cultures() As CultureInfo = { CultureInfo.InvariantCulture,
New CultureInfo("en-US"),
New CultureInfo("fr-FR") }
For Each culture In cultures
Console.WriteLine("{0,-12} {1}", If(String.IsNullOrEmpty(culture.Name),
"Invariant", culture.Name),
dat.ToString("d", culture))
Next
End Sub
End Module
' The example displays the following output:
' Invariant 03/01/2011
' en-US 3/1/2011
' fr-FR 01/03/2011
同樣地,如下列範例所示,單一字串可能會根據剖析作業中使用的慣例文化特性來產生不同的日期。
using namespace System;
using namespace System::Globalization;
void main()
{
String^ dateString = "07/10/2011";
array<CultureInfo^>^ cultures = gcnew array<CultureInfo^> { CultureInfo::InvariantCulture,
CultureInfo::CreateSpecificCulture("en-GB"),
CultureInfo::CreateSpecificCulture("en-US") };
Console::WriteLine("{0,-12} {1,10} {2,8} {3,8}\n", "Date String", "Culture",
"Month", "Day");
for each (CultureInfo^ culture in cultures) {
DateTime date = DateTime::Parse(dateString, culture);
Console::WriteLine("{0,-12} {1,10} {2,8} {3,8}", dateString,
String::IsNullOrEmpty(culture->Name) ?
"Invariant" : culture->Name,
date.Month, date.Day);
}
}
// The example displays the following output:
// Date String Culture Month Day
//
// 07/10/2011 Invariant 7 10
// 07/10/2011 en-GB 10 7
// 07/10/2011 en-US 7 10
using System;
using System.Globalization;
public class Example
{
public static void Main()
{
string dateString = "07/10/2011";
CultureInfo[] cultures = { CultureInfo.InvariantCulture,
CultureInfo.CreateSpecificCulture("en-GB"),
CultureInfo.CreateSpecificCulture("en-US") };
Console.WriteLine("{0,-12} {1,10} {2,8} {3,8}\n", "Date String", "Culture",
"Month", "Day");
foreach (var culture in cultures) {
DateTime date = DateTime.Parse(dateString, culture);
Console.WriteLine("{0,-12} {1,10} {2,8} {3,8}", dateString,
String.IsNullOrEmpty(culture.Name) ?
"Invariant" : culture.Name,
date.Month, date.Day);
}
}
}
// The example displays the following output:
// Date String Culture Month Day
//
// 07/10/2011 Invariant 7 10
// 07/10/2011 en-GB 10 7
// 07/10/2011 en-US 7 10
open System
open System.Globalization
let dateString = "07/10/2011"
let cultures =
[| CultureInfo.InvariantCulture
CultureInfo.CreateSpecificCulture "en-GB"
CultureInfo.CreateSpecificCulture "en-US" |]
printfn $"""{"Date String",-12} {"Culture",10} {"Month",8} {"Day",8}\n"""
for culture in cultures do
let date = DateTime.Parse(dateString, culture)
printfn $"""{dateString,-12} {(if String.IsNullOrEmpty culture.Name then "Invariant" else culture.Name),10} {date.Month,8} {date.Day,8}"""
// The example displays the following output:
// Date String Culture Month Day
//
// 07/10/2011 Invariant 7 10
// 07/10/2011 en-GB 10 7
// 07/10/2011 en-US 7 10
Imports System.Globalization
Module Example
Public Sub Main()
Dim dateString As String = "07/10/2011"
Dim cultures() As CultureInfo = { CultureInfo.InvariantCulture,
CultureInfo.CreateSpecificCulture("en-GB"),
CultureInfo.CreateSpecificCulture("en-US") }
Console.WriteLine("{0,-12} {1,10} {2,8} {3,8}", "Date String", "Culture",
"Month", "Day")
Console.WriteLine()
For Each culture In cultures
Dim dat As Date = DateTime.Parse(dateString, culture)
Console.WriteLine("{0,-12} {1,10} {2,8} {3,8}", dateString,
If(String.IsNullOrEmpty(culture.Name),
"Invariant", culture.Name),
dat.Month, dat.Day)
Next
End Sub
End Module
' The example displays the following output:
' Date String Culture Month Day
'
' 07/10/2011 Invariant 7 10
' 07/10/2011 en-GB 10 7
' 07/10/2011 en-US 7 10
字串比較和排序
比較和排序字串的慣例會因文化特性而異。 例如,排序次序可能以注音或字元的視覺表示為基礎。 在東亞語言中,字元會依語意的筆劃和根目錄排序。 排序也取決於字母順序使用的順序語言和文化特性。 例如,丹麥文的 "Æ" 字元在字母順序中排列在 "Z" 之後。 此外,比較可能會區分大小寫或區分大小寫,而大小寫規則可能會因文化特性而異。 另一方面,序數比較會在比較和排序字串時,使用字串中個別字元的 Unicode 字碼點。
排序規則會決定 Unicode 字元的字母順序,以及兩個字串彼此的比較方式。 例如, String.Compare(String, String, StringComparison) 方法會根據 參數比較兩個 StringComparison 字串。 如果參數值為 StringComparison.CurrentCulture ,則方法會執行使用目前文化特性慣例的語言比較;如果參數值為 StringComparison.Ordinal ,則方法會執行序數比較。 因此,如下列範例所示,如果目前的文化特性是美式英文,則第一次呼叫方法 (使用區分文化特性的比較) 會將 「a」 視為小於 「A」,但第二次呼叫 String.Compare(String, String, StringComparison) 相同的方法 (使用序數比較) 會將 「a」 視為大於 「A」。
using namespace System;
using namespace System::Globalization;
using namespace System::Threading;
void main()
{
Thread::CurrentThread->CurrentCulture = CultureInfo::CreateSpecificCulture("en-US");
Console::WriteLine(String::Compare("A", "a", StringComparison::CurrentCulture));
Console::WriteLine(String::Compare("A", "a", StringComparison::Ordinal));
}
// The example displays the following output:
// 1
// -32
using System;
using System.Globalization;
using System.Threading;
public class Example
{
public static void Main()
{
Thread.CurrentThread.CurrentCulture = CultureInfo.CreateSpecificCulture("en-US");
Console.WriteLine(String.Compare("A", "a", StringComparison.CurrentCulture));
Console.WriteLine(String.Compare("A", "a", StringComparison.Ordinal));
}
}
// The example displays the following output:
// 1
// -32
open System
open System.Globalization
open System.Threading
Thread.CurrentThread.CurrentCulture <- CultureInfo.CreateSpecificCulture "en-US"
printfn $"""{String.Compare("A", "a", StringComparison.CurrentCulture)}"""
printfn $"""{String.Compare("A", "a", StringComparison.Ordinal)}"""
// The example displays the following output:
// 1
// -32
Imports System.Globalization
Imports System.Threading
Module Example
Public Sub Main()
Thread.CurrentThread.CurrentCulture = CultureInfo.CreateSpecificCulture("en-US")
Console.WriteLine(String.Compare("A", "a", StringComparison.CurrentCulture))
Console.WriteLine(String.Compare("A", "a", StringComparison.Ordinal))
End Sub
End Module
' The example displays the following output:
' 1
' -32
.NET 支援字組、字串和序數排序規則:
文字排序會執行區分文化特性的字串比較,其中某些非虛構 Unicode 字元可能會有特殊權數指派給它們。 例如,連字號 ( ) 可能會有非常小的權數指派給它,讓 「coop」 和 「co-op」 出現在排序清單中的彼此旁邊。 如需使用字組排序規則比較兩個字串的方法清單 String ,請參閱 依類別排序的字串作業 一節。
字串排序也會執行區分文化特性的比較。 它類似于單字排序,不同之處在于沒有特殊大小寫,而且所有非虛構符號都位於所有英數位元 Unicode 字元之前。 藉由呼叫 CompareInfo.Compare 方法多載,並提供 值為 CompareOptions.StringSort 的參數,即可使用字串排序規則來比較兩個
options
字串。 請注意,這是 .NET 提供的唯一方法,可用來使用字串排序規則來比較兩個字串。序數排序會根據字串中每個 Char 物件的數值來比較字串。 序數比較會自動區分大小寫,因為小寫和大寫版本的字元具有不同的字碼指標。 不過,如果大小寫不重要,您可以指定忽略大小寫的序數比較。 這相當於使用不因文化特性而將字串轉換成大寫,然後在結果上執行序數比較。 如需使用序數排序規則比較兩個字串的方法清單 String ,請參閱 依類別的字串作業 一節。
區分文化特性的比較是明確或隱含使用 CultureInfo 物件的任何比較,包括 屬性所指定的不因文化特性而異 CultureInfo.InvariantCulture 。 隱含文化特性是目前的文化特性,由 和 CultureInfo.CurrentCulture 屬性指定 Thread.CurrentCulture 。 (字母字元的排序次序有相當大的變化,也就是屬性會跨文化特性傳回 true
) 的字元 Char.IsLetter 。 您可以藉由將 物件提供給 CultureInfo 字串比較方法,以 Compare(String, String, CultureInfo, CompareOptions) 指定區分文化特性的比較,以使用特定文化特性的慣例。 您可以指定區分文化特性的比較,這個比較會藉由提供 StringComparison.CurrentCulture 、 StringComparison.CurrentCultureIgnoreCase 或 列舉以外的任何成員 CompareOptionsCompareOptions.Ordinal ,或 CompareOptions.OrdinalIgnoreCase 方法的適當多載,來使用目前文化特性的 Compare 慣例。 區分文化特性的比較通常適用于排序,而序數比較則不適用。 序數比較通常適用于判斷兩個字串是否相等 (,也就是判斷身分識別) ,而區分文化特性的比較則不適用。
下列範例說明區分文化特性和序數比較之間的差異。 此範例會使用序數比較和 da-DK 和 en-US 文化特性的慣例,評估三個字串 「Apple」、「Æble」 和 「AEble」, (其中每一個字串都是呼叫 方法時 Compare 的預設文化特性) 。 由於丹麥文會將字元 「Æ」 視為個別字母,並在字母中的 「Z」 之後排序,因此字串 「Æble」 大於 「Apple」。 不過,「Æble」 不視為相當於 「AEble」,因此 「Æble」 也大於 「AEble」。 en-US 文化特性不包含字母「Æ」,但會將它視為相當於 「AE」,其說明為什麼 「Æble」 小於 「Apple」,但等於 「AEble」。 另一方面,序數比較會將 「Apple」 視為小於 「Æble」,而 「Æble」 則視為大於 「AEble」。
using System;
using System.Globalization;
using System.Threading;
public class CompareStringSample
{
public static void Main()
{
string str1 = "Apple";
string str2 = "Æble";
string str3 = "AEble";
// Set the current culture to Danish in Denmark.
Thread.CurrentThread.CurrentCulture = new CultureInfo("da-DK");
Console.WriteLine("Current culture: {0}",
CultureInfo.CurrentCulture.Name);
Console.WriteLine("Comparison of {0} with {1}: {2}",
str1, str2, String.Compare(str1, str2));
Console.WriteLine("Comparison of {0} with {1}: {2}\n",
str2, str3, String.Compare(str2, str3));
// Set the current culture to English in the U.S.
Thread.CurrentThread.CurrentCulture = new CultureInfo("en-US");
Console.WriteLine("Current culture: {0}",
CultureInfo.CurrentCulture.Name);
Console.WriteLine("Comparison of {0} with {1}: {2}",
str1, str2, String.Compare(str1, str2));
Console.WriteLine("Comparison of {0} with {1}: {2}\n",
str2, str3, String.Compare(str2, str3));
// Perform an ordinal comparison.
Console.WriteLine("Ordinal comparison");
Console.WriteLine("Comparison of {0} with {1}: {2}",
str1, str2,
String.Compare(str1, str2, StringComparison.Ordinal));
Console.WriteLine("Comparison of {0} with {1}: {2}",
str2, str3,
String.Compare(str2, str3, StringComparison.Ordinal));
}
}
// The example displays the following output:
// Current culture: da-DK
// Comparison of Apple with Æble: -1
// Comparison of Æble with AEble: 1
//
// Current culture: en-US
// Comparison of Apple with Æble: 1
// Comparison of Æble with AEble: 0
//
// Ordinal comparison
// Comparison of Apple with Æble: -133
// Comparison of Æble with AEble: 133
open System
open System.Globalization
open System.Threading
let str1 = "Apple"
let str2 = "Æble"
let str3 = "AEble"
// Set the current culture to Danish in Denmark.
Thread.CurrentThread.CurrentCulture <- CultureInfo "da-DK"
printfn $"Current culture: {CultureInfo.CurrentCulture.Name}"
printfn $"Comparison of {str1} with {str2}: {String.Compare(str1, str2)}"
printfn $"Comparison of {str2} with {str3}: {String.Compare(str2, str3)}\n"
// Set the current culture to English in the U.S.
Thread.CurrentThread.CurrentCulture <- CultureInfo "en-US"
printfn $"Current culture: {CultureInfo.CurrentCulture.Name}"
printfn $"Comparison of {str1} with {str2}: {String.Compare(str1, str2)}"
printfn $"Comparison of {str2} with {str3}: {String.Compare(str2, str3)}\n"
// Perform an ordinal comparison.
printfn "Ordinal comparison"
printfn $"Comparison of {str1} with {str2}: {String.Compare(str1, str2, StringComparison.Ordinal)}"
printfn $"Comparison of {str2} with {str3}: {String.Compare(str2, str3, StringComparison.Ordinal)}"
// The example displays the following output:
// Current culture: da-DK
// Comparison of Apple with Æble: -1
// Comparison of Æble with AEble: 1
//
// Current culture: en-US
// Comparison of Apple with Æble: 1
// Comparison of Æble with AEble: 0
//
// Ordinal comparison
// Comparison of Apple with Æble: -133
// Comparison of Æble with AEble: 133
Imports System.Globalization
Imports System.Threading
Public Module Example
Public Sub Main()
Dim str1 As String = "Apple"
Dim str2 As String = "Æble"
Dim str3 As String = "AEble"
' Set the current culture to Danish in Denmark.
Thread.CurrentThread.CurrentCulture = New CultureInfo("da-DK")
Console.WriteLine("Current culture: {0}",
CultureInfo.CurrentCulture.Name)
Console.WriteLine("Comparison of {0} with {1}: {2}",
str1, str2, String.Compare(str1, str2))
Console.WriteLine("Comparison of {0} with {1}: {2}",
str2, str3, String.Compare(str2, str3))
Console.WriteLine()
' Set the current culture to English in the U.S.
Thread.CurrentThread.CurrentCulture = New CultureInfo("en-US")
Console.WriteLine("Current culture: {0}",
CultureInfo.CurrentCulture.Name)
Console.WriteLine("Comparison of {0} with {1}: {2}",
str1, str2, String.Compare(str1, str2))
Console.WriteLine("Comparison of {0} with {1}: {2}",
str2, str3, String.Compare(str2, str3))
Console.WriteLine()
' Perform an ordinal comparison.
Console.WriteLine("Ordinal comparison")
Console.WriteLine("Comparison of {0} with {1}: {2}",
str1, str2,
String.Compare(str1, str2, StringComparison.Ordinal))
Console.WriteLine("Comparison of {0} with {1}: {2}",
str2, str3,
String.Compare(str2, str3, StringComparison.Ordinal))
End Sub
End Module
' The example displays the following output:
' Current culture: da-DK
' Comparison of Apple with Æble: -1
' Comparison of Æble with AEble: 1
'
' Current culture: en-US
' Comparison of Apple with Æble: 1
' Comparison of Æble with AEble: 0
'
' Ordinal comparison
' Comparison of Apple with Æble: -133
' Comparison of Æble with AEble: 133
使用下列一般指導方針來選擇適當的排序或字串比較方法:
如果您想要根據使用者的文化特性排序字串,您應該根據目前文化特性的慣例來排序字串。 如果使用者的文化特性變更,排序字串的順序也會隨之變更。 例如,同義字應用程式應該一律根據使用者的文化特性來排序單字。
如果您想要根據特定文化特性的慣例來排序字串,您應該藉由提供 CultureInfo 代表該文化特性的物件給比較方法來排序這些字串。 例如,在設計為教導學生特定語言的應用程式中,您想要根據其中一種說話該語言的文化特性慣例來排序字串。
如果您希望字串的順序在文化特性之間保持不變,您應該根據不因文化特性而異的慣例來排序它們,或使用序數比較。 例如,您可以使用序數排序來組織檔案、進程、Mutex 或具名管道的名稱。
如需涉及安全性決策的比較 (,例如使用者名稱是否有效) ,您應該一律呼叫 方法的多 Equals 載來執行相等的序數測試。
注意
字串比較中使用的區分文化特性排序和大小寫規則取決於 .NET 的版本。 在 .NET Core 上,字串比較取決於基礎作業系統支援的 Unicode Standard 版本。 在 windows 8 或更新版本上執行的 .NET Framework 4.5 和更新版本中,排序、大小寫、正規化和 Unicode 字元資訊符合 Unicode 6.0 標準。 在其他 Windows 作業系統上,它們符合 Unicode 5.0 標準。
如需字組、字串和序數排序規則的詳細資訊,請參閱 System.Globalization.CompareOptions 主題。 如需何時使用每個規則的其他建議,請參閱 使用字串的最佳做法。
通常,您不會呼叫字串比較方法,例如 Compare 直接判斷字串的排序次序。 相反地,比較方法會藉由排序 方法呼叫,例如 Array.Sort 或 List<T>.Sort 。 下列範例會執行四個不同的排序作業, (使用目前文化特性的字組排序、使用不因文化特性而異的字組排序、序數排序,以及使用不因文化特性而異的字串排序) 而不明確呼叫字串比較方法,不過它們確實指定要使用的比較類型。 請注意,每種類型的排序都會在其陣列中產生字串的唯一順序。
using namespace System;
using namespace System::Collections;
using namespace System::Collections::Generic;
using namespace System::Globalization;
// IComparer<String> implementation to perform string sort.
ref class SCompare : System::Collections::Generic::IComparer<String^>
{
public:
SCompare() {};
virtual int Compare(String^ x, String^ y)
{
return CultureInfo::CurrentCulture->CompareInfo->Compare(x, y, CompareOptions::StringSort);
}
};
void main()
{
array<String^>^ strings = gcnew array<String^> { "coop", "co-op", "cooperative",
L"co\x00ADoperative", L"c�ur", "coeur" };
// Perform a word sort using the current (en-US) culture.
array<String^>^ current = gcnew array<String^>(strings->Length);
strings->CopyTo(current, 0);
Array::Sort(current, StringComparer::CurrentCulture);
// Perform a word sort using the invariant culture.
array<String^>^ invariant = gcnew array<String^>(strings->Length);
strings->CopyTo(invariant, 0);
Array::Sort(invariant, StringComparer::InvariantCulture);
// Perform an ordinal sort.
array<String^>^ ordinal = gcnew array<String^>(strings->Length);
strings->CopyTo(ordinal, 0);
Array::Sort(ordinal, StringComparer::Ordinal);
// Perform a string sort using the current culture.
array<String^>^ stringSort = gcnew array<String^>(strings->Length);
strings->CopyTo(stringSort, 0);
Array::Sort(stringSort, gcnew SCompare());
// Display array values
Console::WriteLine("{0,13} {1,13} {2,15} {3,13} {4,13}\n",
"Original", "Word Sort", "Invariant Word",
"Ordinal Sort", "String Sort");
for (int ctr = 0; ctr < strings->Length; ctr++)
Console::WriteLine("{0,13} {1,13} {2,15} {3,13} {4,13}",
strings[ctr], current[ctr], invariant[ctr],
ordinal[ctr], stringSort[ctr] );
}
// The example displays the following output:
// Original Word Sort Invariant Word Ordinal Sort String Sort
//
// coop c�ur c�ur co-op co-op
// co-op coeur coeur coeur c�ur
// cooperative coop coop coop coeur
// co�operative co-op co-op cooperative coop
// c�ur cooperative cooperative co�operative cooperative
// coeur co�operative co�operative c�ur co�operative
using System;
using System.Collections;
using System.Collections.Generic;
using System.Globalization;
public class Example
{
public static void Main()
{
string[] strings = { "coop", "co-op", "cooperative",
"co\u00ADoperative", "cœur", "coeur" };
// Perform a word sort using the current (en-US) culture.
string[] current = new string[strings.Length];
strings.CopyTo(current, 0);
Array.Sort(current, StringComparer.CurrentCulture);
// Perform a word sort using the invariant culture.
string[] invariant = new string[strings.Length];
strings.CopyTo(invariant, 0);
Array.Sort(invariant, StringComparer.InvariantCulture);
// Perform an ordinal sort.
string[] ordinal = new string[strings.Length];
strings.CopyTo(ordinal, 0);
Array.Sort(ordinal, StringComparer.Ordinal);
// Perform a string sort using the current culture.
string[] stringSort = new string[strings.Length];
strings.CopyTo(stringSort, 0);
Array.Sort(stringSort, new SCompare());
// Display array values
Console.WriteLine("{0,13} {1,13} {2,15} {3,13} {4,13}\n",
"Original", "Word Sort", "Invariant Word",
"Ordinal Sort", "String Sort");
for (int ctr = 0; ctr < strings.Length; ctr++)
Console.WriteLine("{0,13} {1,13} {2,15} {3,13} {4,13}",
strings[ctr], current[ctr], invariant[ctr],
ordinal[ctr], stringSort[ctr] );
}
}
// IComparer<String> implementation to perform string sort.
internal class SCompare : IComparer<String>
{
public int Compare(string x, string y)
{
return CultureInfo.CurrentCulture.CompareInfo.Compare(x, y, CompareOptions.StringSort);
}
}
// The example displays the following output:
// Original Word Sort Invariant Word Ordinal Sort String Sort
//
// coop cœur cœur co-op co-op
// co-op coeur coeur coeur cœur
// cooperative coop coop coop coeur
// cooperative co-op co-op cooperative coop
// cœur cooperative cooperative cooperative cooperative
// coeur cooperative cooperative cœur cooperative
open System
open System.Collections.Generic
open System.Globalization
// IComparer<String> implementation to perform string sort using an F# object expression.
let scompare =
{ new IComparer<String> with
member _.Compare(x, y) =
CultureInfo.CurrentCulture.CompareInfo.Compare(x, y, CompareOptions.StringSort) }
let strings = [| "coop"; "co-op"; "cooperative"; "co\u00ADoperative"; "cœur"; "coeur" |]
// Perform a word sort using the current (en-US) culture.
let current = Array.copy strings
Array.Sort(current, StringComparer.CurrentCulture)
// Perform a word sort using the invariant culture.
let invariant = Array.copy strings
Array.Sort(invariant, StringComparer.InvariantCulture)
// Perform an ordinal sort.
let ordinal = Array.copy strings
Array.Sort(ordinal, StringComparer.Ordinal)
// Perform a string sort using the current culture.
let stringSort = Array.copy strings
Array.Sort(stringSort, scompare)
// Display array values
printfn "%13s %13s %15s %13s %13s\n" "Original" "Word Sort" "Invariant Word" "Ordinal Sort" "String Sort"
for i = 0 to strings.Length - 1 do
printfn "%13s %13s %15s %13s %13s\n" strings[i] current[i] invariant[i] ordinal[i] stringSort[i]
// The example displays the following output:
// Original Word Sort Invariant Word Ordinal Sort String Sort
//
// coop cœur cœur co-op co-op
// co-op coeur coeur coeur cœur
// cooperative coop coop coop coeur
// cooperative co-op co-op cooperative coop
// cœur cooperative cooperative cooperative cooperative
// coeur cooperative cooperative cœur cooperative
Imports System.Collections
Imports System.Collections.Generic
Imports System.Globalization
Module Example
Public Sub Main()
Dim strings() As String = { "coop", "co-op", "cooperative",
"co" + ChrW(&h00AD) + "operative",
"cœur", "coeur" }
' Perform a word sort using the current (en-US) culture.
Dim current(strings.Length - 1) As String
strings.CopyTo(current, 0)
Array.Sort(current, StringComparer.CurrentCulture)
' Perform a word sort using the invariant culture.
Dim invariant(strings.Length - 1) As String
strings.CopyTo(invariant, 0)
Array.Sort(invariant, StringComparer.InvariantCulture)
' Perform an ordinal sort.
Dim ordinal(strings.Length - 1) As String
strings.CopyTo(ordinal, 0)
Array.Sort(ordinal, StringComparer.Ordinal)
' Perform a string sort using the current culture.
Dim stringSort(strings.Length - 1) As String
strings.CopyTo(stringSort, 0)
Array.Sort(stringSort, new SCompare())
' Display array values
Console.WriteLine("{0,13} {1,13} {2,15} {3,13} {4,13}",
"Original", "Word Sort", "Invariant Word",
"Ordinal Sort", "String Sort")
Console.WriteLine()
For ctr As Integer = 0 To strings.Length - 1
Console.WriteLine("{0,13} {1,13} {2,15} {3,13} {4,13}",
strings(ctr), current(ctr), invariant(ctr),
ordinal(ctr), stringSort(ctr))
Next
End Sub
End Module
' IComparer<String> implementation to perform string sort.
Friend Class SCompare : Implements IComparer(Of String)
Public Function Compare(x As String, y As String) As Integer _
Implements IComparer(Of String).Compare
Return CultureInfo.CurrentCulture.CompareInfo.Compare(x, y, CompareOptions.StringSort)
End Function
End Class
' The example displays the following output:
' Original Word Sort Invariant Word Ordinal Sort String Sort
'
' coop cœur cœur co-op co-op
' co-op coeur coeur coeur cœur
' cooperative coop coop coop coeur
' cooperative co-op co-op cooperative coop
' cœur cooperative cooperative cooperative cooperative
' coeur cooperative cooperative cœur cooperative
提示
在內部,.NET 會使用排序索引鍵來支援區分文化特性的字串比較。 字串中的每個字元都會獲得數種排序權數類別,包括字母、大小寫和讀音符號。 類別所代表的 SortKey 排序索引鍵會針對特定字串提供這些權數的存放庫。 如果您的 app 在同一組字串上執行大量搜尋或排序作業,您可以產生和儲存其使用之所有字串的排序索引鍵,以改善其效能。 需要排序或比較作業時,您可以使用排序索引鍵,而不是字串。 如需詳細資訊,請參閱 SortKey 類別。
如果您未指定字串比較慣例,排序方法,例如 Array.Sort(Array) 對字串執行區分文化特性、區分大小寫的排序。 下列範例說明變更目前文化特性如何影響陣列中排序字串的順序。 它會建立三個字串的陣列。 首先,它會將 System.Threading.Thread.CurrentThread.CurrentCulture
屬性設定為 en-US,並呼叫 Array.Sort(Array) 方法。 產生的排序次序是以英文 (美國) 文化特性的排序慣例為基礎。 接下來,此範例會將 System.Threading.Thread.CurrentThread.CurrentCulture
屬性設定為 da-DK,並再次呼叫 Array.Sort 方法。 請注意產生的排序次序與 en-US 結果有何不同,因為它使用丹麥 (丹麥) 的排序慣例。
using System;
using System.Globalization;
using System.Threading;
public class ArraySort
{
public static void Main(String[] args)
{
// Create and initialize a new array to store the strings.
string[] stringArray = { "Apple", "Æble", "Zebra"};
// Display the values of the array.
Console.WriteLine( "The original string array:");
PrintIndexAndValues(stringArray);
// Set the CurrentCulture to "en-US".
Thread.CurrentThread.CurrentCulture = new CultureInfo("en-US");
// Sort the values of the array.
Array.Sort(stringArray);
// Display the values of the array.
Console.WriteLine("After sorting for the culture \"en-US\":");
PrintIndexAndValues(stringArray);
// Set the CurrentCulture to "da-DK".
Thread.CurrentThread.CurrentCulture = new CultureInfo("da-DK");
// Sort the values of the Array.
Array.Sort(stringArray);
// Display the values of the array.
Console.WriteLine("After sorting for the culture \"da-DK\":");
PrintIndexAndValues(stringArray);
}
public static void PrintIndexAndValues(string[] myArray)
{
for (int i = myArray.GetLowerBound(0); i <=
myArray.GetUpperBound(0); i++ )
Console.WriteLine("[{0}]: {1}", i, myArray[i]);
Console.WriteLine();
}
}
// The example displays the following output:
// The original string array:
// [0]: Apple
// [1]: Æble
// [2]: Zebra
//
// After sorting for the "en-US" culture:
// [0]: Æble
// [1]: Apple
// [2]: Zebra
//
// After sorting for the culture "da-DK":
// [0]: Apple
// [1]: Zebra
// [2]: Æble
open System
open System.Globalization
open System.Threading
let printIndexAndValues (myArray: string[]) =
for i = myArray.GetLowerBound 0 to myArray.GetUpperBound 0 do
printfn $"[{i}]: {myArray[i]}"
printfn ""
// Create and initialize a new array to store the strings.
let stringArray = [| "Apple"; "Æble"; "Zebra" |]
// Display the values of the array.
printfn "The original string array:"
printIndexAndValues stringArray
// Set the CurrentCulture to "en-US".
Thread.CurrentThread.CurrentCulture <- CultureInfo "en-US"
// Sort the values of the array.
Array.Sort stringArray
// Display the values of the array.
printfn "After sorting for the culture \"en-US\":"
printIndexAndValues stringArray
// Set the CurrentCulture to "da-DK".
Thread.CurrentThread.CurrentCulture <- CultureInfo "da-DK"
// Sort the values of the Array.
Array.Sort stringArray
// Display the values of the array.
printfn "After sorting for the culture \"da-DK\":"
printIndexAndValues stringArray
// The example displays the following output:
// The original string array:
// [0]: Apple
// [1]: Æble
// [2]: Zebra
//
// After sorting for the "en-US" culture:
// [0]: Æble
// [1]: Apple
// [2]: Zebra
//
// After sorting for the culture "da-DK":
// [0]: Apple
// [1]: Zebra
// [2]: Æble
Imports System.Globalization
Imports System.IO
Imports System.Threading
Public Class TextToFile
Public Shared Sub Main()
' Creates and initializes a new array to store
' these date/time objects.
Dim stringArray() As String = { "Apple", "Æble", "Zebra"}
' Displays the values of the array.
Console.WriteLine("The original string array:")
PrintIndexAndValues(stringArray)
' Set the CurrentCulture to "en-US".
Thread.CurrentThread.CurrentCulture = New CultureInfo("en-US")
' Sort the values of the Array.
Array.Sort(stringArray)
' Display the values of the array.
Console.WriteLine("After sorting for the ""en-US"" culture:")
PrintIndexAndValues(stringArray)
' Set the CurrentCulture to "da-DK".
Thread.CurrentThread.CurrentCulture = New CultureInfo("da-DK")
' Sort the values of the Array.
Array.Sort(stringArray)
' Displays the values of the Array.
Console.WriteLine("After sorting for the culture ""da-DK"":")
PrintIndexAndValues(stringArray)
End Sub
Public Shared Sub PrintIndexAndValues(myArray() As String)
For i As Integer = myArray.GetLowerBound(0) To myArray.GetUpperBound(0)
Console.WriteLine("[{0}]: {1}", i, myArray(i))
Next
Console.WriteLine()
End Sub
End Class
' The example displays the following output:
' The original string array:
' [0]: Apple
' [1]: Æble
' [2]: Zebra
'
' After sorting for the "en-US" culture:
' [0]: Æble
' [1]: Apple
' [2]: Zebra
'
' After sorting for the culture "da-DK":
' [0]: Apple
' [1]: Zebra
' [2]: Æble
警告
如果比較字串的主要目的是判斷字串是否相等,您應該呼叫 String.Equals 方法。 一般而言,您應該使用 Equals 來執行序數比較。 方法 String.Compare 主要是排序字串。
字串搜尋方法,例如 String.StartsWith 和 String.IndexOf ,也可以執行區分文化特性的序數位符串比較。 下列範例說明使用 IndexOf 方法進行序數與區分文化特性的比較之間的差異。 區分文化特性的搜尋,目前文化特性是英文 (美國) 會將子字串 「oe」 視為符合 ligature 「œ」。 因為虛連字號 (U+00AD) 是零寬度字元,所以搜尋會將軟連字號視為相當於 Empty ,並在字串開頭尋找相符專案。 另一方面,序數搜尋在任一情況下都找不到相符專案。
using namespace System;
void FindInString(String^ s, String^ substring, StringComparison options);
void main()
{
// Search for "oe" and "�u" in "�ufs" and "oeufs".
String^ s1 = L"�ufs";
String^ s2 = L"oeufs";
FindInString(s1, "oe", StringComparison::CurrentCulture);
FindInString(s1, "oe", StringComparison::Ordinal);
FindInString(s2, "�u", StringComparison::CurrentCulture);
FindInString(s2, "�u", StringComparison::Ordinal);
Console::WriteLine();
String^ s3 = L"co\x00ADoperative";
FindInString(s3, L"\x00AD", StringComparison::CurrentCulture);
FindInString(s3, L"\x00AD", StringComparison::Ordinal);
}
void FindInString(String^ s, String^ substring, StringComparison options)
{
int result = s->IndexOf(substring, options);
if (result != -1)
Console::WriteLine("'{0}' found in {1} at position {2}",
substring, s, result);
else
Console::WriteLine("'{0}' not found in {1}",
substring, s);
}
// The example displays the following output:
// 'oe' found in oufs at position 0
// 'oe' not found in oufs
// 'ou' found in oeufs at position 0
// 'ou' not found in oeufs
//
// '-' found in co-operative at position 0
// '-' found in co-operative at position 2
using System;
public class Example
{
public static void Main()
{
// Search for "oe" and "œu" in "œufs" and "oeufs".
string s1 = "œufs";
string s2 = "oeufs";
FindInString(s1, "oe", StringComparison.CurrentCulture);
FindInString(s1, "oe", StringComparison.Ordinal);
FindInString(s2, "œu", StringComparison.CurrentCulture);
FindInString(s2, "œu", StringComparison.Ordinal);
Console.WriteLine();
string s3 = "co\u00ADoperative";
FindInString(s3, "\u00AD", StringComparison.CurrentCulture);
FindInString(s3, "\u00AD", StringComparison.Ordinal);
}
private static void FindInString(string s, string substring, StringComparison options)
{
int result = s.IndexOf(substring, options);
if (result != -1)
Console.WriteLine("'{0}' found in {1} at position {2}",
substring, s, result);
else
Console.WriteLine("'{0}' not found in {1}",
substring, s);
}
}
// The example displays the following output:
// 'oe' found in œufs at position 0
// 'oe' not found in œufs
// 'œu' found in oeufs at position 0
// 'œu' not found in oeufs
//
// '' found in cooperative at position 0
// '' found in cooperative at position 2
open System
let findInString (s: string) (substring: string) (options: StringComparison) =
let result = s.IndexOf(substring, options)
if result <> -1 then
printfn $"'{substring}' found in {s} at position {result}"
else
printfn $"'{substring}' not found in {s}"
// Search for "oe" and "œu" in "œufs" and "oeufs".
let s1 = "œufs"
let s2 = "oeufs"
findInString s1 "oe" StringComparison.CurrentCulture
findInString s1 "oe" StringComparison.Ordinal
findInString s2 "œu" StringComparison.CurrentCulture
findInString s2 "œu" StringComparison.Ordinal
printfn ""
let s3 = "co\u00ADoperative"
findInString s3 "\u00AD" StringComparison.CurrentCulture
findInString s3 "\u00AD" StringComparison.Ordinal
// The example displays the following output:
// 'oe' found in œufs at position 0
// 'oe' not found in œufs
// 'œu' found in oeufs at position 0
// 'œu' not found in oeufs
//
// '' found in cooperative at position 0
// '' found in cooperative at position 2
Module Example
Public Sub Main()
' Search for "oe" and "œu" in "œufs" and "oeufs".
Dim s1 As String = "œufs"
Dim s2 As String = "oeufs"
FindInString(s1, "oe", StringComparison.CurrentCulture)
FindInString(s1, "oe", StringComparison.Ordinal)
FindInString(s2, "œu", StringComparison.CurrentCulture)
FindInString(s2, "œu", StringComparison.Ordinal)
Console.WriteLine()
Dim softHyphen As String = ChrW(&h00AD)
Dim s3 As String = "co" + softHyphen + "operative"
FindInString(s3, softHyphen, StringComparison.CurrentCulture)
FindInString(s3, softHyphen, StringComparison.Ordinal)
End Sub
Private Sub FindInString(s As String, substring As String,
options As StringComparison)
Dim result As Integer = s.IndexOf(substring, options)
If result <> -1
Console.WriteLine("'{0}' found in {1} at position {2}",
substring, s, result)
Else
Console.WriteLine("'{0}' not found in {1}",
substring, s)
End If
End Sub
End Module
' The example displays the following output:
' 'oe' found in œufs at position 0
' 'oe' not found in œufs
' 'œu' found in oeufs at position 0
' 'œu' not found in oeufs
'
' '' found in cooperative at position 0
' '' found in cooperative at position 2
在字串中搜尋
字串搜尋方法,例如 String.StartsWith 和 String.IndexOf ,也可以執行區分文化特性或序數位符串比較,以判斷在指定的字串中找到字元或子字串。
類別中 String 搜尋個別字元的搜尋方法,例如 IndexOf 方法或其中一組字元,例如 IndexOfAny 方法,全都會執行序數搜尋。 若要對字元執行區分文化特性的搜尋,您必須呼叫 CompareInfo 或 之類的 CompareInfo.IndexOf(String, Char)CompareInfo.LastIndexOf(String, Char) 方法。 請注意,使用序數和區分文化特性的比較來搜尋字元的結果可能非常不同。 例如,搜尋預先編譯的 Unicode 字元,例如 ligature 「Æ」 (U+00C6) 可能會符合其任何符合正確序列中的元件,例如 「AE」 (U+041U+0045) 。 下列範例說明在搜尋個別字元時, String.IndexOf(Char) 和 CompareInfo.IndexOf(String, Char) 方法之間的差異。 使用 en-US 文化特性的慣例時,會在字串 「aerial」 中找到 「æ」 (U+00E6) ,但在使用 da-DK 文化特性的慣例或執行序數比較時,則不會找到。
using System;
using System.Globalization;
public class Example
{
public static void Main()
{
String[] cultureNames = { "da-DK", "en-US" };
CompareInfo ci;
String str = "aerial";
Char ch = 'æ'; // U+00E6
Console.Write("Ordinal comparison -- ");
Console.WriteLine("Position of '{0}' in {1}: {2}", ch, str,
str.IndexOf(ch));
foreach (var cultureName in cultureNames) {
ci = CultureInfo.CreateSpecificCulture(cultureName).CompareInfo;
Console.Write("{0} cultural comparison -- ", cultureName);
Console.WriteLine("Position of '{0}' in {1}: {2}", ch, str,
ci.IndexOf(str, ch));
}
}
}
// The example displays the following output:
// Ordinal comparison -- Position of 'æ' in aerial: -1
// da-DK cultural comparison -- Position of 'æ' in aerial: -1
// en-US cultural comparison -- Position of 'æ' in aerial: 0
open System.Globalization
let cultureNames = [| "da-DK"; "en-US" |]
let str = "aerial"
let ch = 'æ' // U+00E6
printf "Ordinal comparison -- "
printfn $"Position of '{ch}' in {str}: {str.IndexOf ch}"
for cultureName in cultureNames do
let ci = CultureInfo.CreateSpecificCulture(cultureName).CompareInfo
printf $"{cultureName} cultural comparison -- "
printfn $"Position of '{ch}' in {str}: {ci.IndexOf(str, ch)}"
// The example displays the following output:
// Ordinal comparison -- Position of 'æ' in aerial: -1
// da-DK cultural comparison -- Position of 'æ' in aerial: -1
// en-US cultural comparison -- Position of 'æ' in aerial: 0
Imports System.Globalization
Module Example
Public Sub Main()
Dim cultureNames() As String = { "da-DK", "en-US" }
Dim ci As CompareInfo
Dim str As String = "aerial"
Dim ch As Char = "æ"c ' U+00E6
Console.Write("Ordinal comparison -- ")
Console.WriteLine("Position of '{0}' in {1}: {2}", ch, str,
str.IndexOf(ch))
For Each cultureName In cultureNames
ci = CultureInfo.CreateSpecificCulture(cultureName).CompareInfo
Console.Write("{0} cultural comparison -- ", cultureName)
Console.WriteLine("Position of '{0}' in {1}: {2}", ch, str,
ci.IndexOf(str, ch))
Next
End Sub
End Module
' The example displays the following output:
' Ordinal comparison -- Position of 'æ' in aerial: -1
' da-DK cultural comparison -- Position of 'æ' in aerial: -1
' en-US cultural comparison -- Position of 'æ' in aerial: 0
另一方面,如果型別的參數未明確指定搜尋選項, String 則搜尋字串而非字元的類別方法會執行區分文化特性的 StringComparison 搜尋。 唯一的例外狀況是 Contains ,它會執行序數搜尋。
測試是否相等
String.Compare使用 方法來判斷排序次序中兩個字串的關聯性。 一般而言,這是區分文化特性的作業。 相反地 String.Equals ,呼叫 方法來測試是否相等。 由於相等的測試通常會比較使用者輸入與一些已知的字串,例如有效的使用者名稱、密碼或檔案系統路徑,所以通常是序數運算。
警告
呼叫 方法並判斷傳回值是否為零,即可測試是否相等 String.Compare 。 不過,不建議這麼做。 若要判斷兩個字串是否相等,您應該呼叫 方法的 String.Equals 其中一個多載。 要呼叫的慣用多載是實例 Equals(String, StringComparison) 方法或靜態 Equals(String, String, StringComparison) 方法,因為兩種方法 System.StringComparison 都包含明確指定比較類型的參數。
下列範例說明當應該改用序數比較時,執行區分文化特性的比較是否相等的危險。 在此情況下,程式碼的意圖是藉由執行不區分大小寫的 URL 與字串 「FILE://」 ,禁止從開頭為 「FILE://」 或 「file://」 的 URL 進行檔案系統存取。 不過,如果使用土耳其文 (土耳其) 以 「file://」 開頭的 URL 上執行區分文化特性的比較,則相等比較會失敗,因為小寫 「i」 的土耳其文大寫對等專案是 「İ」,而不是 「I」。 因此,不小心允許檔案系統存取。 另一方面,如果執行序數比較,則相等比較會成功,而檔案系統存取會遭到拒絕。
using namespace System;
using namespace System::Globalization;
using namespace System::Threading;
bool TestForEquality(String^ str, StringComparison cmp);
void main()
{
Thread::CurrentThread->CurrentCulture = CultureInfo::CreateSpecificCulture("tr-TR");
String^ filePath = "file://c:/notes.txt";
Console::WriteLine("Culture-sensitive test for equality:");
if (! TestForEquality(filePath, StringComparison::CurrentCultureIgnoreCase))
Console::WriteLine("Access to {0} is allowed.", filePath);
else
Console::WriteLine("Access to {0} is not allowed.", filePath);
Console::WriteLine("\nOrdinal test for equality:");
if (! TestForEquality(filePath, StringComparison::OrdinalIgnoreCase))
Console::WriteLine("Access to {0} is allowed.", filePath);
else
Console::WriteLine("Access to {0} is not allowed.", filePath);
}
bool TestForEquality(String^ str, StringComparison cmp)
{
int position = str->IndexOf("://");
if (position < 0) return false;
String^ substring = str->Substring(0, position);
return substring->Equals("FILE", cmp);
}
// The example displays the following output:
// Culture-sensitive test for equality:
// Access to file://c:/notes.txt is allowed.
//
// Ordinal test for equality:
// Access to file://c:/notes.txt is not allowed.
using System;
using System.Globalization;
using System.Threading;
public class Example
{
public static void Main()
{
Thread.CurrentThread.CurrentCulture = CultureInfo.CreateSpecificCulture("tr-TR");
string filePath = "file://c:/notes.txt";
Console.WriteLine("Culture-sensitive test for equality:");
if (! TestForEquality(filePath, StringComparison.CurrentCultureIgnoreCase))
Console.WriteLine("Access to {0} is allowed.", filePath);
else
Console.WriteLine("Access to {0} is not allowed.", filePath);
Console.WriteLine("\nOrdinal test for equality:");
if (! TestForEquality(filePath, StringComparison.OrdinalIgnoreCase))
Console.WriteLine("Access to {0} is allowed.", filePath);
else
Console.WriteLine("Access to {0} is not allowed.", filePath);
}
private static bool TestForEquality(string str, StringComparison cmp)
{
int position = str.IndexOf("://");
if (position < 0) return false;
string substring = str.Substring(0, position);
return substring.Equals("FILE", cmp);
}
}
// The example displays the following output:
// Culture-sensitive test for equality:
// Access to file://c:/notes.txt is allowed.
//
// Ordinal test for equality:
// Access to file://c:/notes.txt is not allowed.
open System
open System.Globalization
open System.Threading
let testForEquality (str: string) (cmp: StringComparison) =
let position = str.IndexOf "://"
if position < 0 then false
else
let substring = str.Substring(0, position)
substring.Equals("FILE", cmp)
Thread.CurrentThread.CurrentCulture <- CultureInfo.CreateSpecificCulture "tr-TR"
let filePath = "file://c:/notes.txt"
printfn "Culture-sensitive test for equality:"
if not (testForEquality filePath StringComparison.CurrentCultureIgnoreCase) then
printfn $"Access to {filePath} is allowed."
else
printfn $"Access to {filePath} is not allowed."
printfn "\nOrdinal test for equality:"
if not (testForEquality filePath StringComparison.OrdinalIgnoreCase) then
printfn $"Access to {filePath} is allowed."
else
printfn $"Access to {filePath} is not allowed."
// The example displays the following output:
// Culture-sensitive test for equality:
// Access to file://c:/notes.txt is allowed.
//
// Ordinal test for equality:
// Access to file://c:/notes.txt is not allowed.
Imports System.Globalization
Imports System.Threading
Module Example
Public Sub Main()
Thread.CurrentThread.CurrentCulture = CultureInfo.CreateSpecificCulture("tr-TR")
Dim filePath As String = "file://c:/notes.txt"
Console.WriteLine("Culture-sensitive test for equality:")
If Not TestForEquality(filePath, StringComparison.CurrentCultureIgnoreCase) Then
Console.WriteLine("Access to {0} is allowed.", filePath)
Else
Console.WriteLine("Access to {0} is not allowed.", filePath)
End If
Console.WriteLine()
Console.WriteLine("Ordinal test for equality:")
If Not TestForEquality(filePath, StringComparison.OrdinalIgnoreCase) Then
Console.WriteLine("Access to {0} is allowed.", filePath)
Else
Console.WriteLine("Access to {0} is not allowed.", filePath)
End If
End Sub
Private Function TestForEquality(str As String, cmp As StringComparison) As Boolean
Dim position As Integer = str.IndexOf("://")
If position < 0 Then Return False
Dim substring As String = str.Substring(0, position)
Return substring.Equals("FILE", cmp)
End Function
End Module
' The example displays the following output:
' Culture-sensitive test for equality:
' Access to file://c:/notes.txt is allowed.
'
' Ordinal test for equality:
' Access to file://c:/notes.txt is not allowed.
正規化
某些 Unicode 字元有多個標記法。 例如,下列任何字碼點都可以代表字母 「ắ」 :
U+1EAF
U+0103 U+0301
U+0061 U+0306 U+0301
單一字元的多個標記法會使搜尋、排序、比對和其他字串作業複雜。
Unicode 標準會定義稱為正規化的程式,它會針對任何對等二進位標記法傳回 Unicode 字元的一個二進位標記法。 正規化可以使用數種演算法,稱為正規化形式,其遵循不同的規則。 .NET 支援 Unicode 正規化表單 C、D、KC 和 KD。 當字串正規化為相同的正規化形式時,可以使用序數比較加以比較。
序數比較是每個字串中對應 Char 物件的 Unicode 純量值的二進位比較。 類別 String 包含一些可執行序數比較的方法,包括下列各項:
包含參數之 Compare 、 Equals 、 StartsWith 、 EndsWith 、 IndexOf 和 LastIndexOf 方法 StringComparison 的任何多載。 如果您提供 或 OrdinalIgnoreCase 的值 StringComparison.Ordinal 給此參數,此方法會執行序數比較。
方法的多 CompareOrdinal 載。
搜尋 Char 值或字串實例中陣列中 Char 專案的方法。 這類方法包括 IndexOf(Char) 和 Split(Char[]) 。
您可以呼叫 String.IsNormalized() 方法,判斷字串是否正規化為正規化表單 C,或者您可以呼叫 String.IsNormalized(NormalizationForm) 方法來判斷字串是否正規化為指定的正規化表單。 您也可以呼叫 String.Normalize() 方法,將字串轉換成正規化表單 C,也可以呼叫 String.Normalize(NormalizationForm) 方法,將字串轉換成指定的正規化表單。 如需正規化和比較字串的逐步資訊,請參閱 Normalize() 和 Normalize(NormalizationForm) 方法。
下列簡單範例說明字串正規化。 它會以三個不同的字串,以三種不同的方式定義字母 「ố」,並使用序數比較來判斷每個字串與其他兩個字串不同。 然後,它會將每個字串轉換成支援的正規化表單,然後再次執行指定正規化表單中每個字串的序數比較。 在每個案例中,第二個相等測試會顯示字串相等。
using namespace System;
using namespace System::Globalization;
using namespace System::IO;
using namespace System::Text;
public ref class Example
{
private:
StreamWriter^ sw;
void TestForEquality(... array<String^>^ words)
{
for (int ctr = 0; ctr <= words->Length - 2; ctr++)
for (int ctr2 = ctr + 1; ctr2 <= words->Length - 1; ctr2++)
sw->WriteLine("{0} ({1}) = {2} ({3}): {4}",
words[ctr], ShowBytes(words[ctr]),
words[ctr2], ShowBytes(words[ctr2]),
words[ctr]->Equals(words[ctr2], StringComparison::Ordinal));
}
String^ ShowBytes(String^ str)
{
String^ result = nullptr;
for each (Char ch in str)
result += String::Format("{0} ", Convert::ToUInt16(ch).ToString("X4"));
return result->Trim();
}
array<String^>^ NormalizeStrings(NormalizationForm nf, ... array<String^>^ words)
{
for (int ctr = 0; ctr < words->Length; ctr++)
if (! words[ctr]->IsNormalized(nf))
words[ctr] = words[ctr]->Normalize(nf);
return words;
}
public:
void Execute()
{
sw = gcnew StreamWriter(".\\TestNorm1.txt");
// Define three versions of the same word.
String^ s1 = L"sống"; // create word with U+1ED1
String^ s2 = L"s\x00F4\x0301ng";
String^ s3 = L"so\x0302\x0301ng";
TestForEquality(s1, s2, s3);
sw->WriteLine();
// Normalize and compare strings using each normalization form.
for each (String^ formName in Enum::GetNames(NormalizationForm::typeid))
{
sw->WriteLine("Normalization {0}:\n", formName);
NormalizationForm nf = (NormalizationForm) Enum::Parse(NormalizationForm::typeid, formName);
array<String^>^ sn = NormalizeStrings(nf, s1, s2, s3 );
TestForEquality(sn);
sw->WriteLine("\n");
}
sw->Close();
}
};
void main()
{
Example^ ex = gcnew Example();
ex->Execute();
}
// The example produces the following output:
// The example displays the following output:
// sống (0073 1ED1 006E 0067) = sống (0073 00F4 0301 006E 0067): False
// sống (0073 1ED1 006E 0067) = sống (0073 006F 0302 0301 006E 0067): False
// sống (0073 00F4 0301 006E 0067) = sống (0073 006F 0302 0301 006E 0067): False
//
// Normalization FormC:
//
// sống (0073 1ED1 006E 0067) = sống (0073 1ED1 006E 0067): True
// sống (0073 1ED1 006E 0067) = sống (0073 1ED1 006E 0067): True
// sống (0073 1ED1 006E 0067) = sống (0073 1ED1 006E 0067): True
//
//
// Normalization FormD:
//
// sống (0073 006F 0302 0301 006E 0067) = sống (0073 006F 0302 0301 006E 0067): True
// sống (0073 006F 0302 0301 006E 0067) = sống (0073 006F 0302 0301 006E 0067): True
// sống (0073 006F 0302 0301 006E 0067) = sống (0073 006F 0302 0301 006E 0067): True
//
//
// Normalization FormKC:
//
// sống (0073 1ED1 006E 0067) = sống (0073 1ED1 006E 0067): True
// sống (0073 1ED1 006E 0067) = sống (0073 1ED1 006E 0067): True
// sống (0073 1ED1 006E 0067) = sống (0073 1ED1 006E 0067): True
//
//
// Normalization FormKD:
//
// sống (0073 006F 0302 0301 006E 0067) = sống (0073 006F 0302 0301 006E 0067): True
// sống (0073 006F 0302 0301 006E 0067) = sống (0073 006F 0302 0301 006E 0067): True
// sống (0073 006F 0302 0301 006E 0067) = sống (0073 006F 0302 0301 006E 0067): True
using System;
using System.Globalization;
using System.IO;
using System.Text;
public class Example
{
private static StreamWriter sw;
public static void Main()
{
sw = new StreamWriter(@".\TestNorm1.txt");
// Define three versions of the same word.
string s1 = "sống"; // create word with U+1ED1
string s2 = "s\u00F4\u0301ng";
string s3 = "so\u0302\u0301ng";
TestForEquality(s1, s2, s3);
sw.WriteLine();
// Normalize and compare strings using each normalization form.
foreach (string formName in Enum.GetNames(typeof(NormalizationForm)))
{
sw.WriteLine("Normalization {0}:\n", formName);
NormalizationForm nf = (NormalizationForm) Enum.Parse(typeof(NormalizationForm), formName);
string[] sn = NormalizeStrings(nf, s1, s2, s3);
TestForEquality(sn);
sw.WriteLine("\n");
}
sw.Close();
}
private static void TestForEquality(params string[] words)
{
for (int ctr = 0; ctr <= words.Length - 2; ctr++)
for (int ctr2 = ctr + 1; ctr2 <= words.Length - 1; ctr2++)
sw.WriteLine("{0} ({1}) = {2} ({3}): {4}",
words[ctr], ShowBytes(words[ctr]),
words[ctr2], ShowBytes(words[ctr2]),
words[ctr].Equals(words[ctr2], StringComparison.Ordinal));
}
private static string ShowBytes(string str)
{
string result = null;
foreach (var ch in str)
result += $"{(ushort)ch:X4} ";
return result.Trim();
}
private static string[] NormalizeStrings(NormalizationForm nf, params string[] words)
{
for (int ctr = 0; ctr < words.Length; ctr++)
if (! words[ctr].IsNormalized(nf))
words[ctr] = words[ctr].Normalize(nf);
return words;
}
}
// The example displays the following output:
// sống (0073 1ED1 006E 0067) = sống (0073 00F4 0301 006E 0067): False
// sống (0073 1ED1 006E 0067) = sống (0073 006F 0302 0301 006E 0067): False
// sống (0073 00F4 0301 006E 0067) = sống (0073 006F 0302 0301 006E 0067): False
//
// Normalization FormC:
//
// sống (0073 1ED1 006E 0067) = sống (0073 1ED1 006E 0067): True
// sống (0073 1ED1 006E 0067) = sống (0073 1ED1 006E 0067): True
// sống (0073 1ED1 006E 0067) = sống (0073 1ED1 006E 0067): True
//
//
// Normalization FormD:
//
// sống (0073 006F 0302 0301 006E 0067) = sống (0073 006F 0302 0301 006E 0067): True
// sống (0073 006F 0302 0301 006E 0067) = sống (0073 006F 0302 0301 006E 0067): True
// sống (0073 006F 0302 0301 006E 0067) = sống (0073 006F 0302 0301 006E 0067): True
//
//
// Normalization FormKC:
//
// sống (0073 1ED1 006E 0067) = sống (0073 1ED1 006E 0067): True
// sống (0073 1ED1 006E 0067) = sống (0073 1ED1 006E 0067): True
// sống (0073 1ED1 006E 0067) = sống (0073 1ED1 006E 0067): True
//
//
// Normalization FormKD:
//
// sống (0073 006F 0302 0301 006E 0067) = sống (0073 006F 0302 0301 006E 0067): True
// sống (0073 006F 0302 0301 006E 0067) = sống (0073 006F 0302 0301 006E 0067): True
// sống (0073 006F 0302 0301 006E 0067) = sống (0073 006F 0302 0301 006E 0067): True
open System
open System.IO
open System.Text
do
use sw = new StreamWriter(@".\TestNorm1.txt")
let showBytes (str: string) =
let mutable result = ""
for ch in str do
result <- result + $"{uint16 ch:X4} "
result.Trim()
let testForEquality (words: string[]) =
for ctr = 0 to words.Length - 2 do
for ctr2 = ctr + 1 to words.Length - 1 do
sw.WriteLine("{0} ({1}) = {2} ({3}): {4}",
words[ctr], showBytes(words[ctr]),
words[ctr2], showBytes(words[ctr2]),
words[ctr].Equals(words[ctr2], StringComparison.Ordinal))
let normalizeStrings nf (words: string[]) =
for i = 0 to words.Length - 1 do
if not (words[i].IsNormalized nf) then
words[i] <- words[i].Normalize nf
words
// Define three versions of the same word.
let s1 = "sống" // create word with U+1ED1
let s2 = "s\u00F4\u0301ng"
let s3 = "so\u0302\u0301ng"
testForEquality [| s1; s2; s3 |]
sw.WriteLine()
// Normalize and compare strings using each normalization form.
for formName in Enum.GetNames typeof<NormalizationForm> do
sw.WriteLine("Normalization {0}:\n", formName)
let nf = Enum.Parse(typeof<NormalizationForm>, formName) :?> NormalizationForm
let sn = normalizeStrings nf [| s1; s2; s3|]
testForEquality sn
sw.WriteLine "\n"
// The example displays the following output:
// sống (0073 1ED1 006E 0067) = sống (0073 00F4 0301 006E 0067): False
// sống (0073 1ED1 006E 0067) = sống (0073 006F 0302 0301 006E 0067): False
// sống (0073 00F4 0301 006E 0067) = sống (0073 006F 0302 0301 006E 0067): False
//
// Normalization FormC:
//
// sống (0073 1ED1 006E 0067) = sống (0073 1ED1 006E 0067): True
// sống (0073 1ED1 006E 0067) = sống (0073 1ED1 006E 0067): True
// sống (0073 1ED1 006E 0067) = sống (0073 1ED1 006E 0067): True
//
//
// Normalization FormD:
//
// sống (0073 006F 0302 0301 006E 0067) = sống (0073 006F 0302 0301 006E 0067): True
// sống (0073 006F 0302 0301 006E 0067) = sống (0073 006F 0302 0301 006E 0067): True
// sống (0073 006F 0302 0301 006E 0067) = sống (0073 006F 0302 0301 006E 0067): True
//
//
// Normalization FormKC:
//
// sống (0073 1ED1 006E 0067) = sống (0073 1ED1 006E 0067): True
// sống (0073 1ED1 006E 0067) = sống (0073 1ED1 006E 0067): True
// sống (0073 1ED1 006E 0067) = sống (0073 1ED1 006E 0067): True
//
//
// Normalization FormKD:
//
// sống (0073 006F 0302 0301 006E 0067) = sống (0073 006F 0302 0301 006E 0067): True
// sống (0073 006F 0302 0301 006E 0067) = sống (0073 006F 0302 0301 006E 0067): True
// sống (0073 006F 0302 0301 006E 0067) = sống (0073 006F 0302 0301 006E 0067): True
Imports System.Globalization
Imports System.IO
Imports System.Text
Module Example
Private sw As StreamWriter
Public Sub Main()
sw = New StreamWriter(".\TestNorm1.txt")
' Define three versions of the same word.
Dim s1 As String = "sống" ' create word with U+1ED1
Dim s2 AS String = "s" + ChrW(&h00F4) + ChrW(&h0301) + "ng"
Dim s3 As String = "so" + ChrW(&h0302) + ChrW(&h0301) + "ng"
TestForEquality(s1, s2, s3)
sw.WriteLine()
' Normalize and compare strings using each normalization form.
For Each formName In [Enum].GetNames(GetType(NormalizationForm))
sw.WriteLine("Normalization {0}:", formName)
Dim nf As NormalizationForm = CType([Enum].Parse(GetType(NormalizationForm), formName),
NormalizationForm)
Dim sn() As String = NormalizeStrings(nf, s1, s2, s3)
TestForEquality(sn)
sw.WriteLine(vbCrLf)
Next
sw.Close()
End Sub
Private Sub TestForEquality(ParamArray words As String())
For ctr As Integer = 0 To words.Length - 2
For ctr2 As Integer = ctr + 1 To words.Length - 1
sw.WriteLine("{0} ({1}) = {2} ({3}): {4}",
words(ctr), ShowBytes(words(ctr)),
words(ctr2), ShowBytes(words(ctr2)),
words(ctr).Equals(words(ctr2), StringComparison.Ordinal))
Next
Next
End Sub
Private Function ShowBytes(str As String) As String
Dim result As String = Nothing
For Each ch In str
result += String.Format("{0} ", Convert.ToUInt16(ch).ToString("X4"))
Next
Return result.Trim()
End Function
Private Function NormalizeStrings(nf As NormalizationForm, ParamArray words() As String) As String()
For ctr As Integer = 0 To words.Length - 1
If Not words(ctr).IsNormalized(nf) Then
words(ctr) = words(ctr).Normalize(nf)
End If
Next
Return words
End Function
End Module
' The example displays the following output:
' sống (0073 1ED1 006E 0067) = sống (0073 00F4 0301 006E 0067): False
' sống (0073 1ED1 006E 0067) = sống (0073 006F 0302 0301 006E 0067): False
' sống (0073 00F4 0301 006E 0067) = sống (0073 006F 0302 0301 006E 0067): False
'
' Normalization FormC:
'
' sống (0073 1ED1 006E 0067) = sống (0073 1ED1 006E 0067): True
' sống (0073 1ED1 006E 0067) = sống (0073 1ED1 006E 0067): True
' sống (0073 1ED1 006E 0067) = sống (0073 1ED1 006E 0067): True
'
'
' Normalization FormD:
'
' sống (0073 006F 0302 0301 006E 0067) = sống (0073 006F 0302 0301 006E 0067): True
' sống (0073 006F 0302 0301 006E 0067) = sống (0073 006F 0302 0301 006E 0067): True
' sống (0073 006F 0302 0301 006E 0067) = sống (0073 006F 0302 0301 006E 0067): True
'
'
' Normalization FormKC:
'
' sống (0073 1ED1 006E 0067) = sống (0073 1ED1 006E 0067): True
' sống (0073 1ED1 006E 0067) = sống (0073 1ED1 006E 0067): True
' sống (0073 1ED1 006E 0067) = sống (0073 1ED1 006E 0067): True
'
'
' Normalization FormKD:
'
' sống (0073 006F 0302 0301 006E 0067) = sống (0073 006F 0302 0301 006E 0067): True
' sống (0073 006F 0302 0301 006E 0067) = sống (0073 006F 0302 0301 006E 0067): True
' sống (0073 006F 0302 0301 006E 0067) = sống (0073 006F 0302 0301 006E 0067): True
如需正規化和正規化表單的詳細資訊,請參閱 System.Text.NormalizationForm 和 Unicode 標準附錄 #15:unicode.org 網站上的 Unicode 正規化表單 和 正規化常見問題 。
依類別排序的字串作業
類別 String 提供比較字串、測試字串是否相等、尋找字串中的字元或子字串、修改字串、從字串擷取子字串、合併字串、格式化值、複製字串,以及正規化字串的成員。
比較字串
您可以使用下列 String 方法來比較字串,以在排序次序中判斷其相對位置:
Compare 會傳回整數,這個整數表示一個字串與排序次序中的第二個字串的關聯性。
CompareOrdinal 會傳回整數,指出一個字串與第二個字串的關聯性,根據其代碼點的比較。
CompareTo 會傳回整數,這個整數表示目前字串實例與排序次序中的第二個字串的關聯性。 方法 CompareTo(String) 會提供 IComparable 類別的 String 和 IComparable<T> 實作。
測試字串是否相等
您可以呼叫 Equals 方法來判斷兩個字串是否相等。 實例 Equals(String, String, StringComparison) 和靜態 Equals(String, StringComparison) 多載可讓您指定比較是否區分文化特性或序數,以及是否考慮或忽略大小寫。 對等性的大部分測試都是序數,而相等比較會決定系統資源的存取權 (,例如檔案系統物件) 一律為序數。
尋找字串中的字元
類別 String 包含兩種搜尋方法:
傳回 Boolean 值的方法,指出特定子字串是否存在於字串實例中。 這些包括 Contains 、 EndsWith 和 StartsWith 方法。
方法,表示子字串在字串實例中的起始位置。 這些包括 IndexOf 、 IndexOfAny 、 LastIndexOf 和 LastIndexOfAny 方法。
警告
如果您想要搜尋特定模式的字串,而不是特定子字串,您應該使用正則運算式。 如需詳細資訊,請參閱 .NET 正則運算式。
修改字串
類別 String 包含下列方法,這些方法看起來會修改字串的值:
PadLeft 在字串開頭插入一或多個指定的字元。
PadRight 在字串結尾插入一或多個指定的字元。
ToLower 並將 ToLowerInvariant 字串中的所有字元轉換成小寫。
ToUpper 並將 ToUpperInvariant 字串中的所有字元轉換成大寫。
Trim 會從字串的開頭和結尾移除所有出現的字元。
TrimEnd 從字串結尾移除所有出現的字元。
TrimStart 會從字串開頭移除所有出現的字元。
重要
所有字串修改方法都會傳回新的 String 物件。 它們不會修改目前實例的值。
從字串擷取子字串
方法會將 String.Split 單一字串分隔成多個字串。 方法的多載可讓您指定多個分隔符號、限制方法擷取的子字串數目、修剪子字串中的空白字元,以及指定分隔符號是否包含在傳回的字串之間時所發生的空字串) (。
合併字串
下列 String 方法可用於字串串連:
格式化值
方法 String.Format 會使用複合格式設定功能,將字串中的一或多個預留位置取代為某些物件或值的字串表示。 方法 Format 通常用來執行下列動作:
在字串中內嵌數值的字串表示。
若要在字串中內嵌日期和時間值的字串表示。
若要在字串中內嵌列舉值的字串表示。
若要內嵌支援 IFormattable 字串中介面之某些物件的字串表示。
若要靠右對齊或靠左對齊較大字串內欄位中的子字串。
如需格式化作業和範例的詳細資訊,請參閱 Format 多載摘要。
編輯字串
您可以呼叫下列 String 方法來建立字串的複本:
正規化字串
在 Unicode 中,單一字元可以有多個字碼指標。 正規化會將這些對等字元轉換成相同的二進位標記法。 方法 String.Normalize 會執行正規化,而 String.IsNormalized 方法會判斷字串是否正規化。
如需詳細資訊和範例,請參閱本主題稍早的 正規化 一節。
建構函式
String(Char*) |
將 String 類別的新執行個體初始化為 Unicode 字元陣列的指定指標所指示的值。 |
String(Char*, Int32, Int32) |
將 String 類別的新執行個體初始化為 Unicode 字元陣列、在陣列內起始字元的位置以及長度等等的指定指標所指示的值。 |
String(Char, Int32) |
將 String 類別的新執行個體初始化為由重複指定次數的指定 Unicode 字元所指示的值。 |
String(Char[]) |
將 String 類別新執行個體初始化為所指定字元陣列中指出的 Unicode 字元。 |
String(Char[], Int32, Int32) |
將 String 類別的新執行個體初始化為 Unicode 字元陣列、在陣列內起始字元的位置和長度等等所指示的值。 |
String(ReadOnlySpan<Char>) |
將 String 類別新執行個體初始化為所指定唯讀範圍中指出的 Unicode 字元。 |
String(SByte*) |
將 String 類別的新執行個體初始化為 8 位元帶正負號整數 (Signed Integer) 陣列的指標所指示的值。 |
String(SByte*, Int32, Int32) |
將 String 類別的新執行個體初始化為 8 位元帶正負號整數的陣列、在該陣列內開始位置和長度的指定指標所指示的值。 |
String(SByte*, Int32, Int32, Encoding) |
將 String 類別的新執行個體初始化為 8 位元帶正負號整數的陣列、在該陣列內開始位置、長度和 Encoding 物件的指定指標所指示的值。 |
欄位
Empty |
表示空字串。 此欄位為唯讀。 |
屬性
Chars[Int32] | |
Length |
取得目前 String 物件中字元的數目。 |
方法
Clone() |
傳回對 String這個執行個體的參考。 |
Compare(String, Int32, String, Int32, Int32) |
比較兩個指定的 String 物件子字串,並傳回一個整數,指出它們在排序順序中的相對位置。 |
Compare(String, Int32, String, Int32, Int32, Boolean) |
比較兩個指定之 String 物件的子字串,忽略或區分兩者的大小寫,並傳回一個整數,表示兩者在排序順序中的相對位置。 |
Compare(String, Int32, String, Int32, Int32, Boolean, CultureInfo) |
比較兩個指定之 String 物件的子字串,忽略或區分兩者的大小寫,並使用文化特性資訊來影響比較,然後傳回一個整數,表示兩者在排序順序中的相對位置。 |
Compare(String, Int32, String, Int32, Int32, CultureInfo, CompareOptions) |
比較兩個指定的 String 物件的子字串,使用指定的比較選項及特定文化特性資訊影響比較,然後傳回整數,這個整數表示這兩個子字串在排序次序中彼此的關聯性。 |
Compare(String, Int32, String, Int32, Int32, StringComparison) |
使用指定的規則比較兩個指定之 String 物件的子字串,並傳回一個整數,表示兩者在排序順序中的相對位置。 |
Compare(String, String) |
比較兩個指定的 String 物件,並傳回一個整數,指出它們在排序順序中的相對位置。 |
Compare(String, String, Boolean) |
比較兩個指定的 String 物件,忽略或區分兩者的大小寫,並傳回一個整數,表示兩者在排序順序中的相對位置。 |
Compare(String, String, Boolean, CultureInfo) |
比較兩個指定的 String 物件,忽略或區分兩者的大小寫,並使用特定文化特性資訊來影響比較,然後傳回一個整數,表示兩者在排序順序中的相對位置。 |
Compare(String, String, CultureInfo, CompareOptions) |
比較兩個指定的 String 物件,使用指定的比較選項及特定文化特性資訊影響比較,然後傳回整數,這個整數表示這兩個字串在排序次序中彼此的關聯性。 |
Compare(String, String, StringComparison) |
使用指定的規則比較兩個指定的 String 物件,並傳回一個整數,表示兩者在排序順序中的相對位置。 |
CompareOrdinal(String, Int32, String, Int32, Int32) | |
CompareOrdinal(String, String) | |
CompareTo(Object) |
比較這個執行個體與指定的 Object,並且指出這個執行個體在排序次序中,位於所指定 Object 之前、之後或相同位置。 |
CompareTo(String) |
比較這個執行個體與指定的 String 物件,並且表示這個執行個體在排序次序中,位於所指定字串之前、之後或相同位置。 |
Concat(IEnumerable<String>) |
串連類型 IEnumerable<T> 之已建構的 String 集合的成員。 |
Concat(Object) |
建立指定物件的字串表示。 |
Concat(Object, Object) |
串連兩個指定之物件的字串表示。 |
Concat(Object, Object, Object) |
串連三個指定之物件的字串表示。 |
Concat(Object, Object, Object, Object) |
串連四個指定的物件之字串表示和選擇性變數長度參數清單中所指定的任何物件。 |
Concat(Object[]) |
串連指定之 Object 陣列中項目的字串表示法。 |
Concat(ReadOnlySpan<Char>, ReadOnlySpan<Char>) |
串連兩個指定唯讀字元範圍的字串表示。 |
Concat(ReadOnlySpan<Char>, ReadOnlySpan<Char>, ReadOnlySpan<Char>) |
串連三個指定唯讀字元範圍的字串表示。 |
Concat(ReadOnlySpan<Char>, ReadOnlySpan<Char>, ReadOnlySpan<Char>, ReadOnlySpan<Char>) |
串連四個指定唯讀字元範圍的字串表示。 |
Concat(String, String) |
串連 String 的兩個指定執行個體。 |
Concat(String, String, String) |
串連 String 的三個指定執行個體。 |
Concat(String, String, String, String) |
串連 String 的四個指定執行個體。 |
Concat(String[]) |
串連指定 String 陣列中的項目。 |
Concat<T>(IEnumerable<T>) |
串連 IEnumerable<T> 實作的成員。 |
Contains(Char) |
傳回值,這個值表示指定的字元是否會出現在這個字串內。 |
Contains(Char, StringComparison) |
使用指定的比較規則傳回值,這個值表示指定的字元是否會出現在這個字串內。 |
Contains(String) |
傳回值,這個值表示指定的子字串是否會出現在這個字串內。 |
Contains(String, StringComparison) |
使用指定的比較規則傳回值,這個值表示指定的字串是否會出現在這個字串內。 |
Copy(String) |
已過時。
|
CopyTo(Int32, Char[], Int32, Int32) |
將字元的指定數目從這個執行個體的指定位置,複製到 Unicode 字元陣列的指定位置。 |
CopyTo(Span<Char>) |
將這個字串的內容複寫到目的地範圍。 |
Create(IFormatProvider, DefaultInterpolatedStringHandler) |
使用指定的提供者來控制指定之插入字串的格式設定,以建立新的字串。 |
Create(IFormatProvider, Span<Char>, DefaultInterpolatedStringHandler) |
使用指定的提供者來控制指定之插入字串的格式設定,以建立新的字串。 |
Create<TState>(Int32, TState, SpanAction<Char,TState>) |
使用指定的回呼,建立具有特定長度的新字串,並在建立後予以初始化。 |
EndsWith(Char) |
判斷這個字串執行個體的結尾是否符合所指定字元。 |
EndsWith(String) |
判斷這個字串執行個體的結尾是否符合指定的字串。 |
EndsWith(String, Boolean, CultureInfo) |
判斷當使用指定之文化特性進行比較時,這個字串執行個體的結尾是否符合指定的字串。 |
EndsWith(String, StringComparison) |
判斷當使用指定的比較選項進行比較時,這個字串執行個體的結尾是否符合指定的字串。 |
EnumerateRunes() |
從這個字串傳回 Rune 的列舉。 |
Equals(Object) |
判斷這個執行個體和指定的物件 (同時還必須是 String 物件) 是否具有相同的值。 |
Equals(String) |
判斷這個執行個體和另一個指定的 String 物件是否具有相同的值。 |
Equals(String, String) |
判斷兩個指定的 String 物件是否具有相同的值。 |
Equals(String, String, StringComparison) |
判斷兩個指定的 String 物件是否具有相同的值。 參數可指定用於比較的文化特性、大小寫及排序規則。 |
Equals(String, StringComparison) |
判斷這個字串和指定的 String 物件是否具有相同的值。 參數可指定用於比較的文化特性、大小寫及排序規則。 |
Format(IFormatProvider, CompositeFormat, Object[]) |
將 中的 CompositeFormat 格式專案或專案取代為指定格式之對應物件的字串表示。 |
Format(IFormatProvider, CompositeFormat, ReadOnlySpan<Object>) |
將 中的 CompositeFormat 格式專案或專案取代為指定格式之對應物件的字串表示。 |
Format(IFormatProvider, String, Object) |
以對應物件的字串表示,取代指定之字串中的一或多個格式項目。 參數提供特定文化特性格式資訊。 |
Format(IFormatProvider, String, Object, Object) |
以兩個指定物件的字串表示,取代字串中的格式項目。 參數提供特定文化特性格式資訊。 |
Format(IFormatProvider, String, Object, Object, Object) |
以三個指定物件的字串表示,取代字串中的格式項目。 參數提供特定文化特性格式資訊。 |
Format(IFormatProvider, String, Object[]) |
以指定陣列中對應物件的字串表示,取代字串中的格式項目。 參數提供特定文化特性格式資訊。 |
Format(String, Object) |
以指定物件的字串表示,取代字串中的一或多個格式項目。 |
Format(String, Object, Object) |
以兩個指定物件的字串表示,取代字串中的格式項目。 |
Format(String, Object, Object, Object) |
以三個指定物件的字串表示,取代字串中的格式項目。 |
Format(String, Object[]) |
以指定陣列中對應物件的字串表示,取代指定之字串中的格式項目。 |
Format<TArg0,TArg1,TArg2>(IFormatProvider, CompositeFormat, TArg0, TArg1, TArg2) |
將 中的 CompositeFormat 格式專案或專案取代為指定格式之對應物件的字串表示。 |
Format<TArg0,TArg1>(IFormatProvider, CompositeFormat, TArg0, TArg1) |
將 中的 CompositeFormat 格式專案或專案取代為指定格式之對應物件的字串表示。 |
Format<TArg0>(IFormatProvider, CompositeFormat, TArg0) |
將 中的 CompositeFormat 格式專案或專案取代為指定格式之對應物件的字串表示。 |
GetEnumerator() |
擷取可以逐一查看這個字串中個別字元的物件。 |
GetHashCode() |
傳回這個字串的雜湊碼。 |
GetHashCode(ReadOnlySpan<Char>) |
傳回所提供唯讀字元範圍的雜湊碼。 |
GetHashCode(ReadOnlySpan<Char>, StringComparison) |
使用指定的規則,傳回所提供唯讀字元範圍的雜湊碼。 |
GetHashCode(StringComparison) |
使用指定規則傳回這個字串的雜湊碼。 |
GetPinnableReference() |
傳回位於索引零的字串元素參考。 這個方法旨在支援 .NET 編譯器,並非由使用者程式碼呼叫。 |
GetType() |
取得目前執行個體的 Type。 (繼承來源 Object) |
GetTypeCode() | |
IndexOf(Char) |
報告這個字串中指定之 Unicode 字元第一次出現時的所在索引 (以零為起始)。 |
IndexOf(Char, Int32) |
報告這個字串中指定之 Unicode 字元第一次出現時的所在索引 (以零為起始)。 搜尋從指定的字元位置開始。 |
IndexOf(Char, Int32, Int32) |
報告這個執行個體中指定之字元第一次出現時的所在索引 (以零為起始)。 搜尋從指定的字元位置開始,並檢視指定數目的字元位置。 |
IndexOf(Char, StringComparison) |
報告這個字串中指定之 Unicode 字元第一次出現時的所在索引 (以零為起始)。 參數會指定要用於指定字元的搜尋類型。 |
IndexOf(String) |
回報這個執行個體中指定之字串第一次出現時的所在索引 (以零為起始)。 |
IndexOf(String, Int32) |
回報這個執行個體中指定之字串第一次出現時的所在索引 (以零為起始)。 搜尋從指定的字元位置開始。 |
IndexOf(String, Int32, Int32) |
回報這個執行個體中指定之字串第一次出現時的所在索引 (以零為起始)。 搜尋從指定的字元位置開始,並檢視指定數目的字元位置。 |
IndexOf(String, Int32, Int32, StringComparison) |
報告目前 String 物件中指定之字串第一次出現時的所在索引 (以零為起始)。 參數會指定目前字串中的開始搜尋位置、目前字串中要搜尋的字元數目,以及要用於指定字串的搜尋類型。 |
IndexOf(String, Int32, StringComparison) |
報告目前 String 物件中指定之字串第一次出現時的所在索引 (以零為起始)。 參數會指定目前字串中的開始搜尋位置和要用於指定字串的搜尋類型。 |
IndexOf(String, StringComparison) |
報告目前 String 物件中指定之字串第一次出現時的所在索引 (以零為起始)。 參數會指定要用於指定字串的搜尋類型。 |
IndexOfAny(Char[]) |
報告指定的 Unicode 字元陣列中,任何字元在這個執行個體中第一次出現時的所在索引 (以零為起始)。 |
IndexOfAny(Char[], Int32) |
報告指定的 Unicode 字元陣列中,任何字元在這個執行個體中第一次出現時的所在索引 (以零為起始)。 搜尋從指定的字元位置開始。 |
IndexOfAny(Char[], Int32, Int32) |
報告指定的 Unicode 字元陣列中,任何字元在這個執行個體中第一次出現時的所在索引 (以零為起始)。 搜尋從指定的字元位置開始,並檢視指定數目的字元位置。 |
Insert(Int32, String) |
傳回新字串,其中已在這個執行個體中指定的索引位置插入指定的字串。 |
Intern(String) |
擷取指定的 String 的系統參考。 |
IsInterned(String) |
擷取對指定 String 的參考。 |
IsNormalized() |
指出這個字串是否為 Unicode 正規化格式 C。 |
IsNormalized(NormalizationForm) |
指出這個字串是否為指定的 Unicode 正規化格式。 |
IsNullOrEmpty(String) |
表示指定的字串是否為 |
IsNullOrWhiteSpace(String) |
表示指定的字串是否為 |
Join(Char, Object[]) |
在每個成員間使用所指定分隔符號來串連物件陣列的字串表示。 |
Join(Char, String[]) |
在每個成員間使用所指定分隔符號來串連字串陣列。 |
Join(Char, String[], Int32, Int32) |
在每個成員間使用所指定分隔符號來串連字串陣列,從位在 |
Join(String, IEnumerable<String>) |
串連類型 IEnumerable<T> 之已建構的 String 集合的成員,並在每個成員之間使用指定的分隔符號。 |
Join(String, Object[]) |
串連物件陣列的項目,並在每個項目之間使用指定的分隔符號。 |
Join(String, String[]) |
串連字串陣列的所有項目,並在每個項目之間使用指定的分隔符號。 |
Join(String, String[], Int32, Int32) |
串連字串陣列的指定項目,並在每個項目之間使用指定的分隔符號。 |
Join<T>(Char, IEnumerable<T>) |
串連集合的成員,並在每個成員之間使用指定的分隔符號。 |
Join<T>(String, IEnumerable<T>) |
串連集合的成員,並在每個成員之間使用指定的分隔符號。 |
LastIndexOf(Char) |
報告這個執行個體中指定之 Unicode 字元最後一次出現時的所在索引 (以零為起始)。 |
LastIndexOf(Char, Int32) |
報告這個執行個體中指定之 Unicode 字元最後一次出現時的所在索引 (以零為起始)。 搜尋會從指定的字元位置開始,然後反向朝字串的開頭進行。 |
LastIndexOf(Char, Int32, Int32) |
報告這個執行個體的子字串中,指定的 Unicode 字元最後一次出現時的所在索引 (以零為起始)。 搜尋會從指定的字元位置開始,然後反向朝字串開頭指定數目的字元位置進行。 |
LastIndexOf(String) |
回報這個執行個體中指定之字串最後一次出現時的所在索引 (以零為起始)。 |
LastIndexOf(String, Int32) |
回報這個執行個體中指定之字串最後一次出現時的所在索引 (以零為起始)。 搜尋會從指定的字元位置開始,然後反向朝字串的開頭進行。 |
LastIndexOf(String, Int32, Int32) |
回報這個執行個體中指定之字串最後一次出現時的所在索引 (以零為起始)。 搜尋會從指定的字元位置開始,然後反向朝字串開頭指定數目的字元位置進行。 |
LastIndexOf(String, Int32, Int32, StringComparison) |
回報這個執行個體中指定之字串最後一次出現時的所在索引 (以零為起始)。 搜尋會從指定的字元位置開始,然後反向朝字串開頭指定數目的字元位置進行。 參數會指定搜尋指定字串時要執行的比較類型。 |
LastIndexOf(String, Int32, StringComparison) |
報告目前 String 物件中指定之字串最後一次出現時的所在索引 (以零為起始)。 搜尋會從指定的字元位置開始,然後反向朝字串的開頭進行。 參數會指定搜尋指定字串時要執行的比較類型。 |
LastIndexOf(String, StringComparison) |
報告目前 String 物件中指定之字串最後一次出現時的所在索引 (以零為起始)。 參數會指定要用於指定字串的搜尋類型。 |
LastIndexOfAny(Char[]) |
報告 Unicode 陣列中的一或多個指定的字元,在這個執行個體中最後一次出現時的所在索引 (以零為起始)。 |
LastIndexOfAny(Char[], Int32) |
報告 Unicode 陣列中的一或多個指定的字元,在這個執行個體中最後一次出現時的所在索引 (以零為起始)。 搜尋會從指定的字元位置開始,然後反向朝字串的開頭進行。 |
LastIndexOfAny(Char[], Int32, Int32) |
報告 Unicode 陣列中的一或多個指定的字元,在這個執行個體中最後一次出現時的所在索引 (以零為起始)。 搜尋會從指定的字元位置開始,然後反向朝字串開頭指定數目的字元位置進行。 |
MemberwiseClone() |
建立目前 Object 的淺層複製。 (繼承來源 Object) |
Normalize() |
傳回新的字串,其文字值與這個字串相同,但是其二進位表示為 Unicode 正規化格式 C。 |
Normalize(NormalizationForm) |
傳回新的字串,其文字值與這個字串相同,但是其二進位表示為特定的 Unicode 正規化格式。 |
PadLeft(Int32) |
傳回新字串,此字串會以空格填補左側至指定的總長度,靠右對齊這個執行個體中的字元。 |
PadLeft(Int32, Char) |
傳回新字串,此字串會以指定的 Unicode 字元填補左側至指定的總長度,靠右對齊這個執行個體中的字元。 |
PadRight(Int32) |
傳回新字串,此字串會以空格填補右側至指定的總長度,靠左對齊這個字串中的字元。 |
PadRight(Int32, Char) |
傳回新字串,此字串會以指定的 Unicode 字元填補右側至指定的總長度,靠左對齊這個字串中的字元。 |
Remove(Int32) |
傳回新字串,其中已刪除目前執行個體中的所有字元 (從指定位置開始到最後一個位置為止)。 |
Remove(Int32, Int32) |
傳回新字串,其中已刪除在目前執行個體中指定位置開始之指定數目的字元。 |
Replace(Char, Char) |
傳回新字串,其中這個執行個體中所有出現的指定 Unicode 字元都取代成其他指定的 Unicode 字元。 |
Replace(String, String) |
傳回新字串,其中目前執行個體中所有出現的指定字串,都取代成其他指定的字串。 |
Replace(String, String, Boolean, CultureInfo) |
傳回新字串,使用提供的文化特性並區分大小寫,將目前執行個體中出現的所有指定字串都替換成另一個指定字串。 |
Replace(String, String, StringComparison) |
傳回新字串,使用提供的比較類型,將目前執行個體中出現的所有指定字串都替換成另一個指定字串。 |
ReplaceLineEndings() |
以 取代目前字串 NewLine 中的所有換行序列。 |
ReplaceLineEndings(String) |
以 取代目前字串 |
Split(Char, Int32, StringSplitOptions) |
根據指定的分隔字元和選擇性選項,將一個字串分割成最多數量的子字串。 根據提供的字元分隔符號,將一個字串分割成最多數量的子字串,並選擇性省略結果中的空白子字串。 |
Split(Char, StringSplitOptions) |
根據指定的分隔字元和選擇性選項,將一個字串分割成數個子字串。 |
Split(Char[]) |
根據指定的分隔字元,將一個字串分割成數個子字串。 |
Split(Char[], Int32) |
根據指定的分隔字元,將一個字串分割成最多的子字串。 |
Split(Char[], Int32, StringSplitOptions) |
根據指定的分隔字元和選擇性選項,將一個字串分割成最多的子字串。 |
Split(Char[], StringSplitOptions) |
根據指定的分隔字元和選項,將一個字串分割成數個子字串。 |
Split(String, Int32, StringSplitOptions) |
根據指定的分隔字串和選擇性選項,將一個字串分割成最多的子字串。 |
Split(String, StringSplitOptions) |
根據所提供字串分隔符號將字串分割成子字串。 |
Split(String[], Int32, StringSplitOptions) |
根據指定的分隔字串和選擇性選項,將一個字串分割成最多的子字串。 |
Split(String[], StringSplitOptions) |
根據指定的分隔字串和選擇性選項,將一個字串分割成數個子字串。 |
StartsWith(Char) |
判斷此字串執行個體是否以指定的字元開頭。 |
StartsWith(String) |
判斷這個字串執行個體的開頭是否符合指定的字串。 |
StartsWith(String, Boolean, CultureInfo) |
判斷當使用指定之文化特性進行比較時,這個字串執行個體的開頭是否符合指定的字串。 |
StartsWith(String, StringComparison) |
判斷當使用指定之比較選項進行比較時,這個字串執行個體的開頭是否符合指定的字串。 |
Substring(Int32) |
從這個執行個體擷取子字串。 子字串會在指定的字元位置開始並繼續到字串的結尾。 |
Substring(Int32, Int32) |
從這個執行個體擷取子字串。 子字串起始於指定的字元位置,並且具有指定的長度。 |
ToCharArray() |
將這個執行個體中的字元複製到 Unicode 字元陣列中。 |
ToCharArray(Int32, Int32) |
將這個執行個體的指定子字串字元複製到 Unicode 字元陣列。 |
ToLower() |
傳回此字串轉換為小寫的版本。 |
ToLower(CultureInfo) |
使用指定之文化特性的大小寫規則,傳回這個字串轉換成小寫的複本。 |
ToLowerInvariant() |
使用不因文化特性而異的大小寫規則,傳回轉換成小寫的這個 String 物件之複本。 |
ToString() |
傳回這個 String 執行個體;不會實際執行轉換。 |
ToString(IFormatProvider) |
傳回這個 String 執行個體;不會實際執行轉換。 |
ToUpper() |
傳回此字串轉換為大寫的版本。 |
ToUpper(CultureInfo) |
使用指定之文化特性的大小寫規則,傳回這個字串轉換成大寫的複本。 |
ToUpperInvariant() |
使用不因文化特性而異的大小寫規則,傳回轉換成大寫的這個 String 物件之複本。 |
Trim() |
移除目前字串開頭和結尾的所有空白字元。 |
Trim(Char) |
移除目前字串字元開頭和結尾的所有字元執行個體。 |
Trim(Char[]) |
移除出現在目前字串開頭和結尾的所有陣列指定字元集。 |
TrimEnd() |
移除目前字串結尾的所有空白字元。 |
TrimEnd(Char) |
移除所有出現在目前字串結尾的字元。 |
TrimEnd(Char[]) |
移除出現在目前字串結尾的所有陣列指定字元集。 |
TrimStart() |
移除目前字串開頭的所有空白字元。 |
TrimStart(Char) |
移除出現在目前字串開頭的所有指定字元。 |
TrimStart(Char[]) |
移除出現在目前字串開頭的所有陣列指定字元集。 |
TryCopyTo(Span<Char>) |
將這個字串的內容複寫到目的地範圍。 |
運算子
Equality(String, String) |
判斷兩個指定的字串是否具有相同的值。 |
Implicit(String to ReadOnlySpan<Char>) |
定義將指定字串隱含轉換成唯讀範圍的字元。 |
Inequality(String, String) |
判斷兩個指定的字串是否具有不同的值。 |
明確介面實作
擴充方法
適用於
執行緒安全性
此型別具備執行緒安全。