Sdílet prostřednictvím


System.String – třída

Tento článek obsahuje doplňující poznámky k referenční dokumentaci pro toto rozhraní API.

Řetězec je sekvenční kolekce znaků, které slouží k reprezentaci textu. Objekt String je sekvenční kolekce System.Char objektů, které představují řetězec; System.Char objekt odpovídá jednotce kódu UTF-16. Hodnota objektu String je obsah sekvenční kolekce System.Char objektů a tato hodnota je neměnná (to znamená jen pro čtení). Další informace o neměnnosti řetězců naleznete v immutability a StringBuilder třídy oddíl. Maximální velikost objektu String v paměti je 2 GB nebo přibližně 1 miliard znaků.

Další informace o kódování Unicode, UTF-16, jednotkách kódu, bodech kódu a Char Rune typech naleznete v tématu Úvod do kódování znaků v .NET.

Vytvoření instance objektu String

Vytvoření instance objektu String můžete provést následujícími způsoby:

  • Přiřazením řetězcového literálu String k proměnné. Jedná se o nejčastěji používanou metodu pro vytvoření řetězce. Následující příklad používá přiřazení k vytvoření několika řetězců. Všimněte si, že v jazyce C# a F# je zpětné lomítko (\) řídicím znakem, musí být v řetězci uvozována zpětná lomítka literálů nebo celý řetězec musí být @-quoted.

    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
    
  • Voláním konstruktoru String třídy Následující příklad vytvoří instance řetězců voláním několika konstruktorů třídy. Všimněte si, že některé konstruktory zahrnují ukazatele na pole znaků nebo podepsaná bajtová pole jako parametry. Visual Basic nepodporuje volání těchto konstruktorů. Podrobné informace o String konstruktorech naleznete v souhrnu konstruktoru String .

    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
    
  • Pomocí operátoru zřetězení řetězců (+ v jazyce C# a F# a & nebo + v jazyce Visual Basic) vytvořte jeden řetězec z libovolné kombinace String instancí a řetězcových literálů. Následující příklad znázorňuje použití operátoru zřetězení řetězce.

    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.
    
  • Načtením vlastnosti nebo voláním metody, která vrací řetězec. Následující příklad používá metody String třídy k extrakci podřetězce z většího řetězce.

    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
    
  • Voláním metody formátování pro převod hodnoty nebo objektu na řetězcové vyjádření. Následující příklad používá funkci složeného formátování k vložení řetězcové reprezentace dvou objektů do řetězce.

    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.
    

Objekty znaků a znaky kódování Unicode

Každý znak v řetězci je definován skalární hodnotou Unicode, která se označuje také jako bod kódu Unicode nebo pořadová (číselná) hodnota znaku Unicode. Každý bod kódu je kódován pomocí kódování UTF-16 a číselná hodnota každého prvku kódování je reprezentována objektem Char .

Poznámka:

Všimněte si, že vzhledem k tomu String , že instance se skládá z sekvenční kolekce jednotek kódu UTF-16, je možné vytvořit String objekt, který není dobře formátovaný řetězec Unicode. Můžete například vytvořit řetězec, který má nízkou náhradu bez odpovídající vysoké náhrady. I když některé metody, jako jsou metody kódování a dekódování objektů v System.Text oboru názvů, mohou provádět kontroly, které zajistí, že řetězce jsou správně formátované, String členové třídy nezajistí, že řetězec je správně formátovaný.

Jeden Char objekt obvykle představuje jeden bod kódu; to znamená číselnou hodnotu Char , která se rovná bodu kódu. Například bod kódu znaku "a" je U+0061. Bod kódu však může vyžadovat více než jeden kódovaný prvek (více než jeden Char objekt). Standard Unicode definuje dva typy znaků, které odpovídají více Char objektům: grafy a doplňkové body kódu Unicode, které odpovídají znakům v doplňkových rovině Unicode.

  • Grafeme je reprezentován základním znakem následovaným jedním nebo více kombinačními znaky. Například znak ä je reprezentován objektem Char , jehož kódový bod je U+0061 následovaný objektem Char , jehož kódovým bodem je U+0308. Tento znak může být definován také jedním Char objektem, který má bod kódu U+00E4. Jak ukazuje následující příklad, porovnání s jazykovou verzí pro rovnost označuje, že tyto dvě reprezentace jsou stejné, i když běžné řadové porovnání ne. Pokud jsou však tyto dva řetězce normalizovány, pořadové porovnání také označuje, že jsou stejné. (Další informace o normalizaci řetězců najdete v tématu Oddíl normalizace .)

    using System;
    using System.Globalization;
    using System.IO;
    
    public class Example5
    {
       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 Example9
        Public Sub Main()
            Dim sw As New StreamWriter(".\graphemes.txt")
            Dim grapheme As String = ChrW(&H61) + ChrW(&H308)
            sw.WriteLine(grapheme)
    
            Dim singleChar As String = ChrW(&HE4)
            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
    
  • Doplňkový bod kódu Unicode (náhradní pár) je reprezentován objektem Char , jehož kódovým bodem je vysoká náhrada následovaná objektem Char , jehož kódovým bodem je nízká náhrada. Jednotky kódu vysokých náhradních dotazů jsou v rozsahu od U+D800 do U+DBFF. Jednotky kódu nízkých náhradních prostředků jsou v rozsahu od U+DC00 do U+DFFF. Náhradní dvojice se používají k reprezentaci znaků v doplňkových rovině 16 Unicode. Následující příklad vytvoří náhradní znak a předá ho Char.IsSurrogatePair(Char, Char) metodě k určení, zda se jedná o náhradní dvojici.

    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 Example20
        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
    

Standard Unicode

Znaky v řetězci jsou reprezentovány kódovými jednotkami kódování UTF-16, které odpovídají hodnotám Char .

Každý znak v řetězci má přidruženou kategorii znaků Unicode, která je reprezentována v .NET výčtem UnicodeCategory . Kategorie znaku nebo náhradní dvojice lze určit voláním CharUnicodeInfo.GetUnicodeCategory metody.

.NET udržuje vlastní tabulku znaků a jejich odpovídající kategorie, což zajišťuje, že konkrétní verze implementace .NET spuštěná na různých platformách vrací informace o stejné kategorii znaků. Informace o kategoriích znaků ve všech verzích .NET a na všech platformách operačního systému poskytují databáze znaků Unicode.

Následující tabulka uvádí verze .NET a verze standardu Unicode, na kterých jsou založeny jejich kategorie znaků.

Verze .NET Verze standardu Unicode
.NET Framework 1.1 Standard Unicode verze 4.0.0
.NET Framework 2,0 Standard Unicode verze 5.0.0
.NET Framework 3.5 Standard Unicode verze 5.0.0
.NET Framework 4 Standard Unicode verze 5.0.0
.NET Framework 4.5 Standard Unicode verze 6.3.0
.NET Framework 4.5.1 Standard Unicode verze 6.3.0
.NET Framework 4.5.2 Standard Unicode verze 6.3.0
.NET Framework 4.6 Standard Unicode verze 6.3.0
.NET Framework 4.6.1 Standard Unicode verze 6.3.0
.NET Framework 4.6.2 a novější verze Standard Unicode verze 8.0.0
.NET Core 2.1 Standard Unicode verze 8.0.0
.NET Core 3.1 Standard Unicode verze 11.0.0
.NET 5 Standard Unicode verze 13.0.0

Rozhraní .NET navíc podporuje porovnávání a řazení řetězců na základě standardu Unicode. Počínaje rozhraním .NET Framework 4.5 spuštěným ve Windows 8 a novějších verzích operačního systému Windows modul runtime deleguje operace porovnání řetězců a řazení do operačního systému. V .NET Core a .NET 5+, porovnání řetězců a řazení informací o knihovnách Unicode (s výjimkou verzí Systému Windows před Aktualizace Windows 10 z května 2019) poskytuje mezinárodní komponenty pro knihovny Unicode. V následující tabulce jsou uvedeny verze rozhraní .NET a verze standardu Unicode, na kterých je založeno porovnání a řazení znaků.

Verze .NET Verze standardu Unicode
.NET Framework 4.5 a novější ve Windows 7 Standard Unicode verze 5.0.0
.NET Framework 4.5 a novější ve Windows 8 a novějších operačních systémech Windows Standard Unicode verze 6.3.0
.NET Core a .NET 5+ Závisí na verzi standardu Unicode, kterou podporuje základní operační systém.

Vložené znaky null

V .NET String může objekt obsahovat vložené znaky null, které se počítají jako součást délky řetězce. V některých jazycích, jako je C a C++, však znak null označuje konec řetězce; není považován za součást řetězce a není počítán jako součást délky řetězce. To znamená, že následující běžné předpoklady, že programátoři nebo knihovny jazyka C++ napsané v jazyce C nebo C++ nemusí být při použití na String objekty nutně platné:

  • Hodnota vrácená strlen funkcemi wcslen se nemusí nutně rovnat String.Length.

  • Řetězec vytvořený funkcemi strcpy_s wcscpy_s nemusí být nutně identický s řetězcem, který se kopíruje.

Měli byste zajistit, aby nativní kód jazyka C a C++, který vytváří instance objektů, a kód předaný String String objekty prostřednictvím volání platformy, nepředpokládá, že vložený znak null označuje konec řetězce.

Vložené znaky null v řetězci jsou také zpracovávány odlišně, pokud je řetězec seřazen (nebo porovnán) a při hledání řetězce. Znaky null jsou ignorovány při provádění porovnání citlivých na jazykové verzi mezi dvěma řetězci, včetně porovnání pomocí invariantní jazykové verze. Považují se pouze za řadové nebo řadové porovnání bez rozlišování malých a malých písmen. Na druhou stranu vložené znaky null jsou vždy považovány za při hledání řetězce pomocí metod, jako Containsje , StartsWitha IndexOf.

Řetězce a indexy

Index je pozice objektu Char (nikoli znaku Unicode) v objektu String. Index je nenegativní číslo, které začíná od první pozice v řetězci, což je pozice indexu nula. Řada vyhledávacích metod, například IndexOf a LastIndexOf, vrátí index znaku nebo podřetězce v instanci řetězce.

Tato Chars[] vlastnost umožňuje přístup k jednotlivým Char objektům podle pozice indexu v řetězci. Chars[] Protože je vlastnost výchozí vlastností (v jazyce Visual Basic) nebo indexer (v jazyce C# a F#), můžete k jednotlivým Char objektům v řetězci přistupovat pomocí kódu, jako je například následující. Tento kód hledá prázdné znaky nebo interpunkční znaky v řetězci a určuje, kolik slov řetězec obsahuje.

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 Example12
    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)) 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.

String Protože třída implementuje IEnumerable rozhraní, můžete také iterovat Char objekty v řetězci pomocí konstruktoruforeach, jak ukazuje následující příklad.

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 Example13
    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.

Po sobě jdoucí hodnoty indexu nemusí odpovídat po sobě jdoucím znakům Unicode, protože znak Unicode může být kódován jako více než jeden Char objekt. Konkrétně řetězec může obsahovat víceznakové jednotky textu, které jsou tvořeny základním znakem následovaným jedním nebo více kombinačními znaky nebo náhradními páry. Chcete-li pracovat s znaky Unicode místo Char objektů, použijte a System.Globalization.StringInfo TextElementEnumerator třídy, nebo metodu String.EnumerateRunes Rune a strukturu. Následující příklad ukazuje rozdíl mezi kódem, který funguje s Char objekty a kódem, který funguje s znaky Unicode. Porovná počet znaků nebo textových prvků v každém slově věty. Řetězec obsahuje dvě sekvence základního znaku následované kombinačním znakem.

// 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 Example14
    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(&H27) 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(&H27) Then Continue Do
            If String.IsNullOrEmpty(s.Trim()) Or (s.Length = 1 AndAlso Char.IsPunctuation(Convert.ToChar(s))) Then
                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

Tento příklad pracuje s textovými prvky pomocí StringInfo.GetTextElementEnumerator metody a TextElementEnumerator třídy k vytvoření výčtu všech textových prvků v řetězci. Můžete také načíst pole, které obsahuje počáteční index každého textového prvku voláním StringInfo.ParseCombiningCharacters metody.

Další informace o práci s jednotkami textu místo jednotlivých Char hodnot naleznete v tématu Úvod do kódování znaků v .NET.

Řetězce null a prázdné řetězce

Řetězec, který byl deklarován, ale nebyl přiřazen, je nullhodnota . Pokus o volání metod v daném řetězci vyvolá .NullReferenceException Řetězec null se liší od prázdného řetězce, což je řetězec, jehož hodnota je "" nebo String.Empty. V některých případech vyvolá výjimku předání řetězce null nebo prázdného řetězce jako argumentu ve volání metody. Například předání řetězce null metodě Int32.Parse vyvolá ArgumentNullExceptionvýjimku a předání prázdného řetězce vyvolá výjimku FormatException. V jiných případech může být argument metody buď řetězec null, nebo prázdný řetězec. Pokud například poskytujete IFormattable implementaci pro třídu, chcete rovnat řetězec null i prázdný řetězec se specifikátorem obecného formátu ("G").

Třída String obsahuje následující dvě metody usnadnění, které umožňují otestovat, zda je null řetězec nebo prázdný:

  • IsNullOrEmpty, který označuje, zda je řetězec buď null nebo je roven String.Empty. Tato metoda eliminuje potřebu používat kód, například následující:

    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, který označuje, zda je nullřetězec , rovná String.Emptynebo se skládá výhradně z prázdných znaků. Tato metoda eliminuje potřebu používat kód, například následující:

    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) Then
    

Následující příklad používá metodu IsNullOrEmpty IFormattable.ToString v implementaci vlastní Temperature třídy. Metoda podporuje řetězce formátu "G", "C", "F" a "K". Pokud prázdný formátovací řetězec nebo formátovací řetězec, jehož hodnota je null předána metodě, jeho hodnota se změní na řetězec formátu "G".

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

Neměnitelnost a třída StringBuilder

Objekt String se nazývá neměnný (jen pro čtení), protože jeho hodnotu nelze po vytvoření změnit. Metody, které se jeví jako úprava objektu String , skutečně vrátí nový String objekt, který obsahuje úpravy.

Vzhledem k tomu, že řetězce jsou neměnné, můžou rutiny manipulace s řetězci, které provádějí opakované sčítání nebo odstranění toho, co se zdá být jedním řetězcem, přesnou významnou pokutu za výkon. Například následující kód používá generátor náhodných čísel k vytvoření řetězce s 1000 znaky v rozsahu 0x0001 k 0x052F. I když se zdá, že kód používá zřetězení řetězců k připojení nového znaku k existujícímu řetězci s názvem str, ve skutečnosti vytvoří nový String objekt pro každou operaci zřetězení.

using System;
using System.IO;
using System.Text;

public class Example6
{
   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 Example10
    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, &H530))
            If str.Length Mod 60 = 0 Then str += vbCrLf
        Next
        sw.Write(str)
        sw.Close()
    End Sub
End Module

Třídu můžete použít StringBuilder místo String třídy pro operace, které dělají více změn hodnoty řetězce. Na rozdíl od instancí String třídy StringBuilder jsou objekty proměnlivé. Při zřetězení, připojení nebo odstranění podřetězců z řetězce se operace provádějí s jedním řetězcem. Po dokončení úpravy hodnoty objektu StringBuilder můžete volat jeho StringBuilder.ToString metodu, která ji převede na řetězec. Následující příklad nahrazuje String použitou v předchozím příkladu ke zřetězení 1000 náhodných znaků v oblasti, která se má 0x0001 0x052F objektem StringBuilder .

using System;
using System.IO;
using System.Text;

public class Example10
{
   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 Example11
    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, &H530)))
            If sb.Length Mod 60 = 0 Then sb.AppendLine()
        Next
        sw.Write(sb.ToString())
        sw.Close()
    End Sub
End Module

Řádové operace vs. operace zohledňující jazykovou verzi

Členové třídy provádějí u objektu String operace citlivé na String řadovou nebo jazykovou jazykovou verzi. Pořadová operace funguje na číselnou hodnotu každého Char objektu. Operace citlivá na jazykovou verzi funguje na hodnotě objektu String a bere v úvahu písmena specifická pro jazykovou verzi, řazení, formátování a parsování pravidel. Operace citlivé na jazykovou verzi se spouštějí v kontextu explicitně deklarované jazykové verze nebo implicitní aktuální jazykové verze. Tyto dva druhy operací můžou při provádění stejného řetězce vytvořit velmi odlišné výsledky.

.NET také podporuje jazykové operace bez ohledu na jazykovou verzi pomocí invariantní jazykové verze (CultureInfo.InvariantCulture), která je volně založená na nastavení jazykové verze anglického jazyka nezávisle na oblasti. Na rozdíl od jiných System.Globalization.CultureInfo nastavení je zaručeno, že nastavení invariantní jazykové verze zůstanou konzistentní na jednom počítači, od systému po systém a napříč verzemi .NET. Invariantní jazykovou verzi lze považovat za druh černé skříňky, která zajišťuje stabilitu porovnání řetězců a řazení ve všech jazykových verzích.

Důležité

Pokud vaše aplikace rozhodne o symbolickém identifikátoru, jako je název souboru nebo pojmenovaný kanál, nebo o trvalých datech, jako jsou textová data v souboru XML, měla by operace místo porovnání citlivé na jazykovou verzi použít pořadové porovnání. Důvodem je to, že porovnání citlivé na jazykovou verzi může přinést různé výsledky v závislosti na jazykové verzi, zatímco pořadové porovnání závisí výhradně na binární hodnotě porovnávaných znaků.

Důležité

Většina metod, které provádějí řetězcové operace, zahrnuje přetížení, které má parametr typu StringComparison, který umožňuje určit, zda metoda provádí řadovou nebo jazykovou verzi operace. Obecně byste měli volat toto přetížení, aby záměr volání metody bylo jasné. Osvědčené postupy a pokyny pro používání řadových a jazykových operací s řetězci najdete v tématu Osvědčené postupy pro používání řetězců.

Operace pro úpravy písmen, parsování a formátování, porovnání a řazení a testování rovnosti můžou být buď řadové, nebo jazykové verze. V následujících částech jsou popsány jednotlivé kategorie operací.

Tip

Vždy byste měli volat přetížení metody, které zjasní záměr volání metody. Například místo volání Compare(String, String) metody k provedení porovnání se dvěma řetězci citlivými na jazykovou verzi pomocí konvencí aktuální jazykové verze byste měli volat Compare(String, String, StringComparison) metodu s hodnotou StringComparison.CurrentCulture argumentu comparisonType . Další informace najdete v tématu Osvědčené postupy pro používání řetězců.

Tabulky hmotnosti řazení, sadu textových souborů, které obsahují informace o hmotnostech znaků použitých při operacích řazení a porovnání, si můžete stáhnout z následujících odkazů:

Velikost písmen

Pravidla velikosti písmen určují, jak změnit velká písmena znaku Unicode; Například z malých písmen na velká písmena. Operace dělení písmen se často provádí před porovnáním řetězců. Například řetězec může být převeden na velká písmena, aby se dal porovnat s jiným velkým řetězcem. Znaky v řetězci můžete převést na malá písmena voláním ToLower nebo ToLowerInvariant metodou a můžete je převést na velká písmena voláním nebo ToUpperInvariant metodouToUpper. Kromě toho můžete použít metodu TextInfo.ToTitleCase k převodu řetězce na velká písmena názvu.

Poznámka:

.NET Core spuštěné jenom v systémech Linux a macOS: Chování kolace pro jazykové verze jazyka C a Posix je vždy citlivé na velká a malá písmena, protože tyto jazykové verze nepoužívají očekávané pořadí kolace Unicode. Doporučujeme použít jinou jazykovou verzi než jazyk C nebo Posix pro provádění operací řazení nerozlišující malá a velká písmena.

Operace casingu mohou být založeny na pravidlech aktuální jazykové verze, zadané jazykové verze nebo invariantní jazykové verze. Vzhledem k tomu, že mapování případů se může lišit v závislosti na použité jazykové verzi, může se výsledek operací velikosti písmen lišit v závislosti na jazykové verzi. Skutečné rozdíly v velikostech jsou tři druhy:

  • Rozdíly v mapování velkých písmen LATINKY I (U+0049), MALÉ PÍSMENO LATINKY I (U+0069), VELKÉ PÍSMENO LATINKY I S TEČKOU NAD (U+0130) a MALÉ PÍSMENO LATINKY I (U+0131). V jazykových verzích tr-TR (Turečtina (Turecko)) a az-Latn-AZ (Ázerbájdžán, Latinka) a v jazykových verzích tr, az-Latn a az-Latn neutrální jazykové verze jsou malými písmeny LATIN CAPITAL LETTER I (LATIN SMALL LETTER DOTLESS I) a velkými písmeny LATIN SMALL LETTER I je VELKÉ PÍSMENO LATINA I S TEČKOU VÝŠE. Vevšechch jazykových verzích jsou malé písmeno I a VELKÉ PÍSMENO LATINKY I a VELKÉ PÍSMENO I.

    Následující příklad ukazuje, jak porovnání řetězců navržené tak, aby zabránilo přístupu k systému souborů, může selhat, pokud spoléhá na porovnání malých písmen citlivých na jazykovou verzi. (Měly by být použity konvence velikostí u invariantní jazykové verze.)

    using System;
    using System.Globalization;
    using System.Threading;
    
    public class Example1
    {
       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 Example2
        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
    
  • Rozdíly v mapování případů mezi neutrální jazykovou verzí a všemi ostatními jazykovými verzemi V těchto případech použití pravidel velikosti písmen invariantní jazykové verze ke změně znaku na velká nebo malá písmena vrátí stejný znak. Pro všechny ostatní jazykové verze vrátí jiný znak. Některé ovlivněné znaky jsou uvedené v následující tabulce.

    Znak Pokud se změní na Návraty
    ZNAMÉNKO MIKRON (U+00B5) Velká písmena ŘECKÉ VELKÉ PÍSMENO MU (U+-39C)
    VELKÉ PÍSMENO LATINKY I S TEČKOU NAD (U+0130) Malá písmena MALÉ PÍSMENO LATINKY I (U+0069)
    MALÉ PÍSMENO LATINKY TEČKA I (U+0131) Velká písmena VELKÉ PÍSMENO LATINKY I (U+0049)
    MALÉ PÍSMENO LATINKY (U+017F) Velká písmena VELKÉ PÍSMENO LATINKY S (U+0053)
    VELKÉ PÍSMENO LATINKY D S MALÝM PÍSMENEM Z S CARON (U+01C5) Malá písmena MALÉ PÍSMENO LATINKY DZ S CARONEM (U+01C6)
    KOMBINOVÁNÍ ŘECKÉHO YPOGEGRAMMENI (U+0345) Velká písmena ŘECKÉ VELKÉ PÍSMENO IOTA (U+0399)
  • Rozdíly v mapování dvoumísmenných párů se smíšenými písmeny v rozsahu znaků ASCII Ve většině jazykových verzí se dvojice dvoumísmenných smíšených písmen rovná ekvivalentní dvoumísmenné nebo malé dvojici písmen. To neplatí pro následující dvojice dvou písmen v následujících jazykových verzích, protože v každém případě se porovnávají s digrafem:

    • "lJ" a "nJ" v kultuře hr-HR (Chorvatština (Chorvatsko)).
    • "cH" v kulturách cs-CZ (Česká republika)) a sk-SK (Slovensko)).
    • "aA" v jazyce da-DK (dánština (Dánsko)).
    • "cS", "dZ", "dZS", "nY", "sZ", "tY" a "zS" v kultuře hu-HU (Maďarsko)).
    • "cH" a "lL" v kultuře es-ES_tradnl (španělsko, tradiční řazení)).
    • "cH", "gI", "kH", "nG" "nH", "pH", "qU', "tH" a "tR" v jazykové verzi vi-VN (Vietnam)).

    Je však neobvyklé narazit na situaci, kdy porovnání těchto párů citlivé na jazykovou verzi vytváří problémy, protože tyto páry jsou v pevných řetězcích nebo identifikátorech neobvyklé.

Následující příklad ukazuje některé rozdíly v pravidlech malých písmen mezi jazykovými verzemi při převodu řetězců na velká písmena.

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 Example1
    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

Analýza a formátování

Formátování a analýza jsou inverzní operace. Pravidla formátování určují, jak převést hodnotu, například datum a čas nebo číslo, na řetězcové vyjádření, zatímco pravidla analýzy určují, jak převést řetězcovou reprezentaci na hodnotu, jako je datum a čas. Pravidla formátování i analýzy jsou závislá na kulturních konvencích. Následující příklad ukazuje nejednoznačnost, která může nastat při interpretaci řetězce data specifického pro jazykovou verzi. Bez znalosti konvencí jazykové verze, která byla použita k vytvoření řetězce kalendářního data, není možné zjistit, zda 03/01/2011, 3.1.2011 a 01.03.2011 představují 3. ledna 2011 nebo 1. března 2011.

using System;
using System.Globalization;

public class Example9
{
   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 Example8
    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

Podobně, jak ukazuje následující příklad, jeden řetězec může vytvořit různá kalendářní data v závislosti na jazykové verzi, jejíž konvence se používají v operaci analýzy.

using System;
using System.Globalization;

public class Example15
{
   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 Example18
    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

Porovnávání a řazení řetězců

Konvence pro porovnávání a řazení řetězců se liší od jazykové verze po jazykovou verzi. Pořadí řazení může být například založeno na fonetice nebo na vizuální reprezentaci znaků. Ve východoasijských jazycích jsou znaky řazeny podle úhozů a radikálu ideografických znaků. Řazení závisí také na pořadí, které jazyky a jazykové verze používají pro abecedu. Dánský jazyk má například znak „Æ“, který se abecedně řadí za znak „Z“. Kromě toho mohou být porovnání malá a velká písmena nerozlišující velká a malá a velká písmena a pravidla velikosti písmen se můžou lišit podle jazykové verze. Pořadové porovnání na druhou stranu používá body kódu Unicode jednotlivých znaků v řetězci při porovnávání a řazení řetězců.

Pravidla řazení určují abecední pořadí znaků Unicode a způsob, jakým se dva řetězce vzájemně porovnávají. Metoda například String.Compare(String, String, StringComparison) porovnává dva řetězce na základě parametru StringComparison . Pokud je StringComparison.CurrentCulturehodnota parametru , metoda provede lingvistické porovnání, které používá konvence aktuální jazykové verze; pokud je StringComparison.Ordinalhodnota parametru , metoda provede pořadové porovnání. Jak ukazuje následující příklad, pokud je aktuální jazyková verze angličtina USA, první volání String.Compare(String, String, StringComparison) metody (pomocí porovnání citlivé na jazykovou verzi) považuje "a" menší než "A", ale druhé volání stejné metody (pomocí řadového porovnání) považuje "a" větší než "A".

using System;
using System.Globalization;
using System.Threading;

public class Example2
{
   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 Example3
    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 podporuje pravidla řazení slov, řetězců a řad:

  • Řazení slov provádí porovnání řetězců citlivých na jazykovou verzi, ve kterých mohou určité znaky Unicode bezphanumeric mít přiřazené speciální váhy. Například spojovník (-) může mít přiřazenou velmi malou váhu, aby se vedle sebe zobrazovaly "coop" a "co-op" v seřazeném seznamu. Seznammetodch String

  • Řazení řetězců také provádí porovnání citlivé na jazykovou verzi. Podobá se řazení slov s tím rozdílem, že neexistují žádné zvláštní případy a všechny neosamocené symboly přicházejí před všechny alfanumerické znaky Unicode. Dva řetězce lze porovnat pomocí pravidel řazení řetězců voláním CompareInfo.Compare přetížení metody, které mají options parametr, který je zadán hodnotu CompareOptions.StringSort. Všimněte si, že jde o jedinou metodu, kterou .NET poskytuje k porovnání dvou řetězců pomocí pravidel řazení řetězců.

  • Řadové řazení porovnává řetězce na základě číselné hodnoty každého Char objektu v řetězci. Pořadové porovnání se automaticky rozlišují malá a velká písmena, protože malá a velká písmena znaku mají různé body kódu. Pokud však případ není důležitý, můžete zadat pořadové porovnání, které ignoruje případ. To je ekvivalentem převodu řetězce na velká písmena pomocí invariantní jazykové verze a následné provedení řadového porovnání výsledku. Seznam String metod, které porovnávají dva řetězce pomocí pravidel řazení řad, najdete v části Operace řetězce podle kategorií .

Porovnání citlivé na jazykovou verzi je jakékoli porovnání, které explicitně nebo implicitně používá CultureInfo objekt, včetně invariantní jazykové verze, která je určena CultureInfo.InvariantCulture vlastností. Implicitní jazyková verze je aktuální jazyková verze, která je určena vlastnostmi a CultureInfo.CurrentCulture vlastnostmiThread.CurrentCulture. V pořadí řazení abecedních znaků (tj. znaků, pro které Char.IsLetter se vlastnost vrací true) napříč jazykovými verzemi existuje značná variace. Můžete zadat porovnání citlivé na jazykovou verzi, které používá konvence konkrétní jazykové verze zadáním CultureInfo objektu do metody porovnání řetězců, například Compare(String, String, CultureInfo, CompareOptions). Můžete určit porovnání citlivé na jazykovou verzi, které používá konvence aktuální jazykové verze zadáním StringComparison.CurrentCulture, StringComparison.CurrentCultureIgnoreCasenebo libovolného člena CompareOptions výčtu jiné než CompareOptions.Ordinal nebo CompareOptions.OrdinalIgnoreCase k příslušné přetížení Compare metody. Porovnání citlivé na jazykovou verzi je obecně vhodné pro řazení, zatímco řadové porovnání není. Řadové porovnání je obecně vhodné pro určení, zda jsou dva řetězce stejné (tj. pro určení identity), zatímco porovnání citlivé na jazykovou verzi není.

Následující příklad ukazuje rozdíl mezi jazykovou verzí a řadovým porovnáním. Příklad vyhodnocuje tři řetězce, "Apple", "Æble" a "AEble", pomocí řadového porovnání a konvencí jazykových verzí da-DK a en-US (každá z nich je výchozí jazykovou verzí v době, Compare kdy se metoda volá). Vzhledem k tomu, že dánský jazyk považuje znak "Æ" za samostatné písmeno a seřadí ho za "Z" v abecedě, řetězec "Æble" je větší než "Apple". "Æble" se však nepovažuje za ekvivalent "AEble", takže "Æble" je také větší než "AEble". Jazyková verze en-US neobsahuje písmeno "Æ", ale považuje ho za ekvivalent "AE", což vysvětluje, proč je "Æble" menší než "Apple", ale rovná se "AEble". Řadové porovnání se na druhou stranu domnívá, že "Apple" je menší než "Æble" a "Æble" musí být větší než "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 Example6
    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

K výběru vhodné metody řazení nebo porovnání řetězců použijte následující obecné pokyny:

  • Pokud chcete, aby se řetězce uspořádaly na základě jazykové verze uživatele, měli byste je uspořádat na základě konvencí aktuální jazykové verze. Pokud se jazyková verze uživatele změní, pořadí seřazených řetězců se také odpovídajícím způsobem změní. Například aplikace tesaurus by měla vždy řadit slova podle jazykové verze uživatele.

  • Pokud chcete, aby se řetězce uspořádaly na základě konvencí konkrétní jazykové verze, měli byste je uspořádat zadáním objektu CultureInfo , který představuje tuto jazykovou verzi metodě porovnání. Například v aplikaci navržené pro výuku studentů určitého jazyka chcete řetězce uspořádat na základě konvencí jedné z jazykových verzí, které tento jazyk mluví.

  • Pokud chcete, aby pořadí řetězců zůstalo beze změny napříč jazykovými verzemi, měli byste je uspořádat na základě konvencí invariantní jazykové verze nebo použít pořadové porovnání. K uspořádání názvů souborů, procesů, mutexů nebo pojmenovaných kanálů byste například použili řadové řazení.

  • Při porovnání, které zahrnuje bezpečnostní rozhodnutí (například zda je uživatelské jméno platné), byste měli vždy provést řadový test rovnosti voláním přetížení Equals metody.

Poznámka:

Pravidla řazení a velikostí písmen používaná v porovnání řetězců citlivá na jazykové verzi závisí na verzi rozhraní .NET. Porovnání řetězců na platformě .NET Core závisí na verzi standardu Unicode podporovaném základním operačním systémem. V rozhraní .NET Framework 4.5 a novějších verzích spuštěných ve Windows 8 nebo novějších verzích, řazení, velikost písmen, normalizace a informace o znakech Unicode odpovídají standardu Unicode 6.0. V jiných operačních systémech Windows odpovídají standardu Unicode 5.0.

Další informace o pravidlech řazení slov, řetězců a řadových řad najdete v System.Globalization.CompareOptions tématu. Další doporučení týkající se použití jednotlivých pravidel najdete v tématu Osvědčené postupy pro používání řetězců.

Obvykle nevoláte metody porovnání řetězců, například Compare přímo k určení pořadí řazení řetězců. Místo toho se metody porovnání volají pomocí metod řazení, jako Array.Sort je nebo List<T>.Sort. Následující příklad provádí čtyři různé operace řazení (řazení slov pomocí aktuální jazykové verze, řazení slov pomocí invariantní jazykové verze, řadového řazení a řazení řetězců pomocí invariantní jazykové verze) bez explicitního volání metody porovnání řetězců, i když určují typ porovnání, který se má použít. Všimněte si, že každý typ řazení vytváří jedinečné pořadí řetězců v poli.

using System;
using System.Collections;
using System.Collections.Generic;
using System.Globalization;
 
public class Example3
{
   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
//     co­operative         co-op           co-op   cooperative          coop
//             cœur   cooperative     cooperative  co­operative   cooperative
//            coeur  co­operative    co­operative          cœur  co­operative
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
//     co­operative         co-op           co-op   cooperative          coop
//             cœur   cooperative     cooperative  co­operative   cooperative
//            coeur  co­operative    co­operative          cœur  co­operative
Imports System.Collections
Imports System.Collections.Generic
Imports System.Globalization

Module Example4
    Public Sub Main()
        Dim strings() As String = {"coop", "co-op", "cooperative",
                                  "co" + ChrW(&HAD) + "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
'     co­operative         co-op           co-op   cooperative          coop
'             cœur   cooperative     cooperative  co­operative   cooperative
'            coeur  co­operative    co­operative          cœur  co­operative

Tip

Rozhraní .NET interně používá klíče řazení k podpoře porovnání řetězců s kulturní citlivostí. Jednotlivým znakům v řetězci je přiřazeno několik kategorií důležitosti řazení, včetně abecedy, velikosti písmen a diakritických znamének. Klíč řazení reprezentovaný SortKey třídou poskytuje úložiště těchto váhy pro určitý řetězec. Pokud vaše aplikace provádí velké množství operací vyhledávání nebo řazení ve stejné sadě řetězců, můžete zlepšit jeho výkon generováním a uložením klíčů řazení pro všechny řetězce, které používá. Pokud je požadována operace řazení nebo porovnání, místo řetězců použijete klíče řazení. Další informace najdete v předmětu SortKey .

Pokud nezadáte konvenci porovnání řetězců, seřazování metod, jako Array.Sort(Array) je například provádění řazení s rozlišováním velkých a malých písmen u řetězců. Následující příklad ukazuje, jak změna aktuální jazykové verze ovlivňuje pořadí seřazených řetězců v poli. Vytvoří pole tří řetězců. Nejprve je vlastnost System.Threading.Thread.CurrentThread.CurrentCulture nastavena na hodnotu en-US a je volána metoda Array.Sort(Array). Výsledné pořadí řazení je založeno na konvencích řazení pro jazykovou verzi angličtiny (USA). Dále je v příkladu vlastnost System.Threading.Thread.CurrentThread.CurrentCulture nastavena na hodnotu da-DK a je znovu volána metoda Array.Sort. Výsledné pořadí se liší od výsledků pro možnost en-US, protože jsou použity konvence řazení pro dánštinu (Dánsko).

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

Upozorňující

Pokud vaším primárním účelem při porovnávání řetězců je určit, zda jsou stejné, měli byste volat metodu String.Equals . Obvykle byste měli použít Equals k provedení řadového porovnání. Metoda String.Compare je určena především k řazení řetězců.

Metody vyhledávání řetězců, například String.StartsWith a String.IndexOf, mohou také provádět porovnání řetězců citlivých na jazykovou verzi nebo řadové řetězce. Následující příklad znázorňuje rozdíly mezi řadovými a jazykovými porovnáními, které používají metodu IndexOf . Hledání citlivé na jazykovou verzi, ve kterém je aktuální jazyková verze angličtina (USA) považuje podřetězce "oe" za shodu ligatury "jazycích". Vzhledem k tomu, že měkký spojovník (U+00AD) je znak nulové šířky, hledání považuje měkké pomlčky za ekvivalentní String.Empty a najde shodu na začátku řetězce. Řadové vyhledávání na druhé straně nenajde shodu v obou případech.

using System;

public class Example8
{
   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 co­operative at position 0
//       '­' found in co­operative 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 co­operative at position 0
//       '­' found in co­operative at position 2
Module Example5
    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(&HAD)
        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 Then
            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 co­operative at position 0
'       '­' found in co­operative at position 2

Hledání v řetězcích

Metody vyhledávání řetězců, například String.StartsWith a String.IndexOf, mohou také provádět porovnání řetězců citlivých na jazykovou verzi nebo řadové řetězce, aby bylo možné určit, zda je znak nebo podřetězec nalezen v zadaném řetězci.

Vyhledávací metody ve String třídě, které hledají jednotlivý znak, například metodu IndexOf , nebo jednu ze sady znaků, jako IndexOfAny je například metoda, provádějí všechna pořadové vyhledávání. Chcete-li provést hledání znaku citlivé na jazykovou verzi, musíte volat metodu CompareInfo , například CompareInfo.IndexOf(String, Char) nebo CompareInfo.LastIndexOf(String, Char). Všimněte si, že výsledky hledání znaku pomocí řadového a jazykového porovnání mohou být velmi odlišné. Například hledání předkomposovaného znaku Unicode, jako je ligatura "Æ" (U+00C6), může v závislosti na jazykové verzi odpovídat jakémukoli výskytu jeho součástí ve správném pořadí, například "AE" (U+041U+0045). Následující příklad ukazuje rozdíl mezi String.IndexOf(Char) a CompareInfo.IndexOf(String, Char) metodami při hledání jednotlivých znaků. Ligatura "æ" (U+00E6) se nachází v řetězci "letecký" při použití konvencí jazykové verze en-US, ale ne při použití konvencí jazykové verze da-DK nebo při provádění pořadového porovnání.

using System;
using System.Globalization;

public class Example17
{
   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 Example19
    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

Na druhou stranu metody třídy, které hledají řetězec místo znaku, provádějí vyhledávání citlivé na jazykovou verzi, String pokud možnosti hledání nejsou explicitně určeny parametrem typu StringComparison. Jedinou výjimkou je Contains, který provádí řadové vyhledávání.

Testování rovnosti

Použijte metodu String.Compare k určení relace dvou řetězců v pořadí řazení. Obvykle se jedná o operaci citlivou na jazykovou verzi. Naproti tomu volejte metodu String.Equals , která testuje rovnost. Vzhledem k tomu, že test rovnosti obvykle porovnává vstup uživatele s nějakým známým řetězcem, jako je platné uživatelské jméno, heslo nebo cesta k systému souborů, je to obvykle pořadová operace.

Upozorňující

Je možné otestovat rovnost voláním String.Compare metody a určením, zda vrácená hodnota je nula. Tento postup se však nedoporučuje. Chcete-li zjistit, zda jsou dva řetězce stejné, měli byste volat jedno z přetížení String.Equals metody. Upřednostňované přetížení volání je buď metoda instance Equals(String, StringComparison) , nebo statická Equals(String, String, StringComparison) metoda, protože obě metody zahrnují System.StringComparison parametr, který explicitně určuje typ porovnání.

Následující příklad znázorňuje nebezpečí, že se místo toho použije pořadové číslo, které je třeba použít při porovnávání citlivé na jazykovou verzi. V tomto případě je záměrem kódu zakázat přístup systému souborů z adres URL začínajících na "FILE://" nebo "file://" provedením porovnání začátku adresy URL bez rozlišování velkých a malých písmen s řetězcem "FILE://". Pokud se však porovnání citlivé na jazykovou verzi provádí pomocí turecké jazykové verze (Turecko) na adrese URL, která začíná na "file://", porovnání rovnosti selže, protože turečtina velká písmena ekvivalentní malými písmeny "i" je "İ" místo "I". V důsledku toho je přístup k systému souborů neúmyslně povolen. Na druhou stranu, pokud je provedeno pořadové porovnání, porovnání rovnosti proběhne úspěšně a přístup k systému souborů je odepřen.

using System;
using System.Globalization;
using System.Threading;

public class Example4
{
   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 Example7
    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.

Normalizace

Některé znaky Unicode mají více reprezentací. Například jakýkoli z následujících bodů kódu může představovat písmeno "ắ":

  • U+1EAF
  • U+0103 U+0301
  • U+0061 U+0306 U+0301

Více reprezentací jednoho znaku komplikuje vyhledávání, řazení, porovnávání a další řetězcové operace.

Standard Unicode definuje proces označovaný jako normalizace, který vrací jednu binární reprezentaci znaku Unicode pro libovolnou z ekvivalentních binárních reprezentací. Normalizace může používat několik algoritmů, označovaných jako normalizační formuláře, které se řídí různými pravidly. .NET podporuje formuláře normalizace unicode C, D, KC a KD. Pokud jsou řetězce normalizovány do stejného formátu normalizace, lze je porovnat pomocí řadového porovnání.

Pořadové porovnání je binární porovnání skalární hodnoty Unicode odpovídajících Char objektů v každém řetězci. Třída String obsahuje řadu metod, které mohou provádět řadové porovnání, včetně následujících:

Můžete určit, zda je řetězec normalizován do normalizace formuláře C voláním String.IsNormalized() metody, nebo můžete volat metodu String.IsNormalized(NormalizationForm) k určení, zda je řetězec normalizován na zadaný normalizační formulář. Můžete také volat metodu String.Normalize() pro převod řetězce na normalizaci formuláře C, nebo můžete volat metodu String.Normalize(NormalizationForm) pro převod řetězce na zadaný normalizační formulář. Podrobné informace o normalizaci a porovnávání řetězců najdete v tématech Normalize() a Normalize(NormalizationForm) metodách.

Následující jednoduchý příklad znázorňuje normalizaci řetězců. Definuje písmeno "ố" třemi různými způsoby třemi různými řetězci a pomocí pořadového porovnání rovnosti určí, že se každý řetězec liší od ostatních dvou řetězců. Potom převede každý řetězec na podporované formuláře normalizace a znovu provede řadové porovnání každého řetězce v zadaném normalizačním formuláři. V každém případě druhý test rovnosti ukazuje, že řetězce jsou stejné.

using System;
using System.Globalization;
using System.IO;
using System.Text;

public class Example13
{
   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 Example16
    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(&HF4) + ChrW(&H301) + "ng"
        Dim s3 As String = "so" + ChrW(&H302) + ChrW(&H301) + "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

Další informace o normalizačních a normalizačních formulářích najdete v článku System.Text.NormalizationForma také standardní příloha Unicode č. 15: Normalizační formuláře Unicode a nejčastější dotazy k normalizaci na unicode.org webu.

Operace s řetězci podle kategorie

String Třída poskytuje členy pro porovnávání řetězců, testování řetězců pro rovnost, hledání znaků nebo podřetězců v řetězci, úpravy řetězce, extrahování podřetězců z řetězce, kombinování řetězců, formátování hodnot, kopírování řetězce a normalizaci řetězce.

Porovnávání řetězců

Pomocí následujících String metod můžete porovnat řetězce a určit jejich relativní pozici v pořadí řazení:

  • Compare vrátí celé číslo, které označuje relaci jednoho řetězce k druhému řetězci v pořadí řazení.

  • CompareOrdinal vrátí celé číslo, které označuje relaci jednoho řetězce k druhému řetězci na základě porovnání jejich bodů kódu.

  • CompareTo vrátí celé číslo, které označuje relaci aktuální instance řetězce k druhému řetězci v pořadí řazení. Metoda CompareTo(String) poskytuje IComparable a IComparable<T> implementace pro String třídu.

Testovací řetězce pro rovnost

Zavoláte metodu Equals , která určí, zda jsou dva řetězce stejné. Instance Equals(String, String, StringComparison) a statické Equals(String, StringComparison) přetížení umožňují určit, zda je porovnání citlivé na jazykovou verzi nebo řadové, a zda je případ považován za nebo ignorován. Většina testů rovnosti je řadová a porovnání rovnosti, která určují přístup k systémovému prostředku (například objektu systému souborů), by měla být vždy pořadová.

Vyhledání znaků v řetězci

Třída String obsahuje dva druhy vyhledávacích metod:

Upozorňující

Pokud chcete vyhledat konkrétní vzor místo konkrétního podřetězce, měli byste použít regulární výrazy. Další informace naleznete v tématu Regulární výrazy .NET.

Úprava řetězce

Třída String obsahuje následující metody, které se zdá upravit hodnotu řetězce:

  • Insert vloží řetězec do aktuální String instance.

  • PadLeft vloží jeden nebo více výskytů zadaného znaku na začátek řetězce.

  • PadRight vloží jeden nebo více výskytů zadaného znaku na konec řetězce.

  • Remove odstraní podřetěrce z aktuální String instance.

  • Replace nahradí podřetětěce jiným podřetědcem v aktuální String instanci.

  • ToLower a ToLowerInvariant převeďte všechny znaky v řetězci na malá písmena.

  • ToUpper a ToUpperInvariant převeďte všechny znaky v řetězci na velká písmena.

  • Trim odebere všechny výskyty znaku od začátku a konce řetězce.

  • TrimEnd odebere všechny výskyty znaku z konce řetězce.

  • TrimStart odebere všechny výskyty znaku od začátku řetězce.

Důležité

Všechny metody úprav řetězců vrací nový String objekt. Neupravují hodnotu aktuální instance.

Extrahování podřetězců z řetězce

Metoda String.Split odděluje jeden řetězec do více řetězců. Přetížení metody umožňují určit více oddělovačů, omezit počet podřetězců, které metoda extrahuje, oříznout prázdné znaky z podřetězců a určit, zda jsou prázdné řetězce (které se vyskytují, když oddělovače sousedí) jsou zahrnuty mezi vrácené řetězce.

Kombinování řetězců

Pro zřetězení řetězců se dají použít následující String metody:

  • Concat kombinuje jeden nebo více podřetězců do jednoho řetězce.
  • Join zřetězí jeden nebo více podřetězců do jednoho prvku a přidá oddělovač mezi každý podřetězce.

Formátování hodnot

Metoda String.Format používá funkci složeného formátování k nahrazení jednoho nebo více zástupných symbolů v řetězci řetězcovou reprezentací některého objektu nebo hodnoty. Metoda Format se často používá k provedení následujících kroků:

  • Vložení řetězcové reprezentace číselné hodnoty do řetězce
  • Vložení řetězcové reprezentace hodnoty data a času do řetězce
  • Vložení řetězcové reprezentace hodnoty výčtu do řetězce
  • Chcete-li vložit řetězcovou reprezentaci některého objektu IFormattable , který podporuje rozhraní v řetězci.
  • Pokud chcete zarovnat do bloku doprava nebo doleva, zarovnat podřetězce v poli v rámci většího řetězce.

Podrobné informace o operacích formátování a příkladech najdete v souhrnu Format přetížení.

Zkopírování řetězce

K vytvoření kopie řetězce můžete volat následující String metody:

  • Clone vrátí odkaz na existující String objekt.
  • CopyTo zkopíruje část řetězce do pole znaků.

Normalizace řetězce

V kódování Unicode může mít jeden znak více bodů kódu. Normalizace převede tyto ekvivalentní znaky na stejnou binární reprezentaci. Metoda String.Normalize provádí normalizaci a String.IsNormalized metoda určuje, zda je řetězec normalizován.

Další informace a příklad najdete v části Normalizace výše v tomto článku.