Classe System.String

Questo articolo fornisce osservazioni supplementari alla documentazione di riferimento per questa API.

Una stringa è una raccolta sequenziale di caratteri che viene usata per rappresentare il testo. Un String oggetto è una raccolta sequenziale di System.Char oggetti che rappresentano una stringa. Un System.Char oggetto corrisponde a un'unità di codice UTF-16. Il valore dell'oggetto String è il contenuto della raccolta sequenziale di System.Char oggetti e tale valore non è modificabile, ovvero è di sola lettura. Per altre informazioni sull'immutabilità delle stringhe, vedere la sezione Immutability and the StringBuilder class .For more information about the immutability of strings, see the Immutability and the StringBuilder class section. La dimensione massima di un String oggetto in memoria è di 2 GB o di circa 1 miliardo di caratteri.

Per altre informazioni su Unicode, UTF-16, unità di codice, punti di codice e tipi Char e Rune , vedere Introduzione alla codifica dei caratteri in .NET.

Creare un'istanza di un oggetto String

È possibile creare un'istanza di un String oggetto nei modi seguenti:

  • Assegnando un valore letterale stringa a una String variabile. Si tratta del metodo più comunemente usato per la creazione di una stringa. Nell'esempio seguente viene utilizzata l'assegnazione per creare più stringhe. Si noti che in C# e F#, poiché la barra rovesciata (\) è un carattere di escape, le barre rovesciate letterali in una stringa devono essere precedute da caratteri di escape o l'intera stringa deve essere @-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
    
  • Chiamando un String costruttore di classe. Nell'esempio seguente viene creata un'istanza di stringhe chiamando diversi costruttori di classi. Si noti che alcuni costruttori includono puntatori a matrici di caratteri o matrici di byte firmate come parametri. Visual Basic non supporta le chiamate a questi costruttori. Per informazioni dettagliate sui String costruttori, vedere il riepilogo del String costruttore.

    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
    
  • Usando l'operatore di concatenazione di stringhe (+ in C# e F#, e & or + in Visual Basic) per creare una singola stringa da qualsiasi combinazione di String istanze e valori letterali stringa. Nell'esempio seguente viene illustrato l'uso dell'operatore di concatenazione di stringhe.

    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.
    
  • Recuperando una proprietà o chiamando un metodo che restituisce una stringa. Nell'esempio seguente vengono utilizzati i metodi della String classe per estrarre una sottostringa da una stringa più grande.

    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
    
  • Chiamando un metodo di formattazione per convertire un valore o un oggetto nella relativa rappresentazione di stringa. Nell'esempio seguente viene utilizzata la funzionalità di formattazione composita per incorporare la rappresentazione di stringa di due oggetti in una stringa.

    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.
    

Oggetti Char e caratteri Unicode

Ogni carattere in una stringa è definito da un valore scalare Unicode, detto anche punto di codice Unicode o valore ordinale (numerico) del carattere Unicode. Ogni punto di codice viene codificato usando la codifica UTF-16 e il valore numerico di ogni elemento della codifica è rappresentato da un Char oggetto .

Nota

Si noti che, poiché un'istanza String è costituita da una raccolta sequenziale di unità di codice UTF-16, è possibile creare un String oggetto che non sia una stringa Unicode ben formata. Ad esempio, è possibile creare una stringa con un surrogato basso senza un surrogato elevato corrispondente. Anche se alcuni metodi, ad esempio i metodi di codifica e decodifica degli oggetti nello System.Text spazio dei nomi, possono eseguire controlli per assicurarsi che le stringhe siano ben formate, String i membri della classe non assicurano che una stringa sia ben formata.

Un singolo Char oggetto rappresenta in genere un singolo punto di codice, ovvero il valore numerico dell'oggetto Char è uguale al punto di codice. Ad esempio, il punto di codice per il carattere "a" è U+0061. Tuttavia, un punto di codice potrebbe richiedere più di un elemento codificato (più di un Char oggetto). Lo standard Unicode definisce due tipi di caratteri che corrispondono a più Char oggetti: gragrafi e punti di codice supplementari Unicode che corrispondono ai caratteri nei piani supplementari Unicode.

  • Un grafo è rappresentato da un carattere di base seguito da uno o più caratteri combinati. Ad esempio, il carattere ä è rappresentato da un Char oggetto il cui punto di codice è U+0061 seguito da un Char oggetto il cui punto di codice è U+0308. Questo carattere può essere definito anche da un singolo Char oggetto con un punto di codice U+00E4. Come illustrato nell'esempio seguente, un confronto sensibile alle impostazioni cultura per l'uguaglianza indica che queste due rappresentazioni sono uguali, anche se un confronto ordinale ordinario non lo è. Tuttavia, se le due stringhe vengono normalizzate, un confronto ordinale indica anche che sono uguali. Per altre informazioni sulla normalizzazione delle stringhe, vedere Sezione normalizzazione.

    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
    
  • Un punto di codice supplementare Unicode (coppia di surrogati) è rappresentato da un Char oggetto il cui punto di codice è un surrogato elevato seguito da un Char oggetto il cui punto di codice è un surrogato basso. Le unità di codice di surrogati alti vanno da U+D800 a U+DBFF. Le unità di codice di surrogati bassi vanno da U+DC00 a U+DFFF. Le coppie surrogate vengono usate per rappresentare i caratteri nei 16 piani supplementari Unicode. L'esempio seguente crea un carattere surrogato e lo passa al Char.IsSurrogatePair(Char, Char) metodo per determinare se si tratta di una coppia di surrogati.

    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

I caratteri in una stringa sono rappresentati da unità di codice con codifica UTF-16, che corrispondono ai Char valori.

Ogni carattere in una stringa ha una categoria di caratteri Unicode associata, rappresentata in .NET dall'enumerazione UnicodeCategory . La categoria di un carattere o di una coppia di surrogati può essere determinata chiamando il CharUnicodeInfo.GetUnicodeCategory metodo .

.NET gestisce una propria tabella di caratteri e le relative categorie, per assicurare che una versione specifica di un'implementazione .NET in esecuzione su piattaforme diverse restituisca informazioni identiche sulle categorie di caratteri. In tutte le versioni di .NET e in tutte le piattaforme del sistema operativo, le informazioni sulle categorie di caratteri vengono fornite dal database di caratteri Unicode.

Nella tabella seguente sono elencate le versioni di .NET e le versioni dello standard Unicode su cui si basano le categorie di caratteri.

Versione di .NET Versione dello standard Unicode
.NET Framework 1.1 Standard Unicode, versione 4.0.0
.NET Framework 2.0 Standard Unicode, versione 5.0.0
.NET Framework 3.5 Standard Unicode, versione 5.0.0
.NET Framework 4 Standard Unicode, versione 5.0.0
.NET Framework 4.5 Standard Unicode, versione 6.3.0
.NET Framework 4.5.1 Standard Unicode, versione 6.3.0
.NET Framework 4.5.2 Standard Unicode, versione 6.3.0
.NET Framework 4.6 Standard Unicode, versione 6.3.0
.NET Framework 4.6.1 Standard Unicode, versione 6.3.0
.NET Framework 4.6.2 e versioni successive Standard Unicode, versione 8.0.0
.NET Core 2.1 Standard Unicode, versione 8.0.0
.NET Core 3.1 Standard Unicode, versione 11.0.0
.NET 5 Standard Unicode, versione 13.0.0

.NET supporta inoltre il confronto e l'ordinamento delle stringhe in base allo standard Unicode. A partire da .NET Framework 4.5 in esecuzione in Windows 8 e versioni successive del sistema operativo Windows, il runtime delega il confronto delle stringhe e le operazioni di ordinamento al sistema operativo. In .NET Core e .NET 5+, le informazioni di confronto e ordinamento delle stringhe vengono fornite dai componenti internazionali per le librerie Unicode (ad eccezione delle versioni di Windows precedenti a Aggiornamento di Windows 10 (maggio 2019)). Nella tabella seguente sono elencate le versioni di .NET e le versioni dello standard Unicode su cui si basano il confronto e l'ordinamento dei caratteri.

Versione di .NET Versione dello standard Unicode
.NET Framework 4.5 e versioni successive in Windows 7 Standard Unicode, versione 5.0.0
.NET Framework 4.5 e versioni successive nei sistemi operativi Windows 8 e versioni successive Standard Unicode, versione 6.3.0
.NET Core e .NET 5+ Dipende dalla versione dello standard Unicode supportato dal sistema operativo sottostante.

Caratteri Null incorporati

In .NET un String oggetto può includere caratteri Null incorporati, che vengono conteggiati come parte della lunghezza della stringa. Tuttavia, in alcuni linguaggi come C e C++, un carattere Null indica la fine di una stringa; non viene considerato una parte della stringa e non viene conteggiato come parte della lunghezza della stringa. Ciò significa che i presupposti comuni seguenti che i programmatori O le librerie C e C++ scritti in C o C++ potrebbero non essere necessariamente validi quando applicati agli String oggetti :

  • Il valore restituito dalle strlen funzioni o wcslen non è necessariamente uguale a String.Length.

  • La stringa creata dalle strcpy_s funzioni o wcscpy_s non è necessariamente identica alla stringa creata dal String.Copy metodo .

È necessario assicurarsi che il codice C e C++ nativo che crea un'istanza degli String oggetti e che il codice passato String tramite platform invoke non presupporre che un carattere Null incorporato contrassegni la fine della stringa.

I caratteri Null incorporati in una stringa vengono trattati in modo diverso anche quando una stringa viene ordinata (o confrontata) e quando viene eseguita la ricerca di una stringa. I caratteri Null vengono ignorati durante l'esecuzione di confronti sensibili alle impostazioni cultura tra due stringhe, inclusi i confronti usando le impostazioni cultura invarianti. Vengono considerati solo per confronti ordinali o ordinali senza distinzione tra maiuscole e minuscole. D'altra parte, i caratteri Null incorporati vengono sempre considerati durante la ricerca di una stringa con metodi come Contains, StartsWithe IndexOf.

Stringhe e indici

Un indice è la posizione di un Char oggetto (non un carattere Unicode) in un oggetto String. Un indice è un numero non negativo in base zero che inizia dalla prima posizione nella stringa, ovvero la posizione di indice zero. Diversi metodi di ricerca, ad esempio IndexOf e LastIndexOf, restituiscono l'indice di un carattere o di una sottostringa nell'istanza della stringa.

La Chars[] proprietà consente di accedere a singoli Char oggetti in base alla posizione dell'indice nella stringa. Poiché la Chars[] proprietà è la proprietà predefinita (in Visual Basic) o l'indicizzatore (in C# e F#), è possibile accedere ai singoli Char oggetti in una stringa usando codice come il seguente. Questo codice cerca spazi vuoti o caratteri di punteggiatura in una stringa per determinare il numero di parole contenute nella stringa.

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.

Poiché la String classe implementa l'interfaccia IEnumerable , è anche possibile scorrere gli Char oggetti in una stringa usando un foreach costrutto, come illustrato nell'esempio seguente.

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.

I valori di indice consecutivi potrebbero non corrispondere ai caratteri Unicode consecutivi, perché un carattere Unicode potrebbe essere codificato come più di un Char oggetto. In particolare, una stringa può contenere unità di testo multi-carattere formate da un carattere di base seguito da una o più coppie di caratteri combinati o da coppie di surrogati. Per usare i caratteri Unicode anziché Char gli oggetti , usare le System.Globalization.StringInfo classi e TextElementEnumerator oppure il String.EnumerateRunes metodo e lo Rune struct . L'esempio seguente illustra la differenza tra il codice che funziona con Char oggetti e codice che funziona con caratteri Unicode. Confronta il numero di caratteri o elementi di testo in ogni parola di una frase. La stringa include due sequenze di un carattere di base seguito da un carattere combinato.

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

Questo esempio funziona con gli elementi di testo usando il StringInfo.GetTextElementEnumerator metodo e la TextElementEnumerator classe per enumerare tutti gli elementi di testo in una stringa. È anche possibile recuperare una matrice contenente l'indice iniziale di ogni elemento di testo chiamando il StringInfo.ParseCombiningCharacters metodo .

Per altre informazioni sull'uso di unità di testo anziché di singoli Char valori, vedere Introduzione alla codifica dei caratteri in .NET.

Stringhe Null e stringhe vuote

Una stringa dichiarata ma non assegnata a un valore è null. Il tentativo di chiamare metodi su tale stringa genera un'eccezione NullReferenceException. Una stringa Null è diversa da una stringa vuota, ovvero una stringa il cui valore è "" o String.Empty. In alcuni casi, il passaggio di una stringa Null o di una stringa vuota come argomento in una chiamata al metodo genera un'eccezione. Ad esempio, il passaggio di una stringa Null al Int32.Parse metodo genera un'eccezione ArgumentNullExceptione il passaggio di una stringa vuota genera un'eccezione FormatException. In altri casi, un argomento del metodo può essere una stringa Null o una stringa vuota. Ad esempio, se si fornisce un'implementazione IFormattable per una classe, si vuole associare sia una stringa Null che una stringa vuota con l'identificatore di formato generale ("G").

La String classe include i due metodi pratici seguenti che consentono di verificare se una stringa è null o vuota:

  • IsNullOrEmpty, che indica se una stringa è null o è uguale a String.Empty. Questo metodo elimina la necessità di usare codice come il seguente:

    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, che indica se una stringa è null, uguale String.Emptya o è costituita esclusivamente da spazi vuoti. Questo metodo elimina la necessità di usare codice come il seguente:

    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
    

Nell'esempio seguente viene usato il IsNullOrEmpty metodo nell'implementazione IFormattable.ToString di una classe personalizzata Temperature . Il metodo supporta le stringhe di formato "G", "C", "F" e "K". Se una stringa di formato vuota o una stringa di formato il cui valore viene null passato al metodo, il relativo valore viene modificato nella stringa di formato "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

Immutabilità e la classe StringBuilder

Un String oggetto viene chiamato non modificabile (di sola lettura), perché il relativo valore non può essere modificato dopo la creazione. I metodi che sembrano modificare un String oggetto restituiscono effettivamente un nuovo String oggetto che contiene la modifica.

Poiché le stringhe non sono modificabili, le routine di manipolazione delle stringhe che eseguono aggiunte o eliminazioni ripetute a ciò che sembra essere una singola stringa possono determinare una riduzione significativa delle prestazioni. Ad esempio, il codice seguente usa un generatore di numeri casuali per creare una stringa con 1000 caratteri nell'intervallo 0x0001 per 0x052F. Anche se il codice sembra usare la concatenazione di stringhe per aggiungere un nuovo carattere alla stringa esistente denominata str, crea effettivamente un nuovo String oggetto per ogni operazione di concatenazione.

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

È possibile usare la StringBuilder classe anziché la String classe per le operazioni che apportano più modifiche al valore di una stringa. A differenza delle istanze della String classe, StringBuilder gli oggetti sono modificabili. Quando si concatenano, accodano o eliminano sottostringhe da una stringa, le operazioni vengono eseguite su una singola stringa. Al termine della modifica del valore di un StringBuilder oggetto, è possibile chiamare il StringBuilder.ToString relativo metodo per convertirlo in una stringa. Nell'esempio seguente viene sostituito l'oggetto String utilizzato nell'esempio precedente per concatenare 1000 caratteri casuali nell'intervallo per 0x0001 per 0x052F con un StringBuilder oggetto .

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

Operazioni ordinali e sensibili alle impostazioni cultura

I membri della String classe eseguono operazioni ordinali o sensibili alle impostazioni cultura (linguistico) su un String oggetto . Un'operazione ordinale agisce sul valore numerico di ogni Char oggetto. Un'operazione sensibile alle impostazioni cultura agisce sul valore dell'oggetto String e prende in considerazione maiuscole e minuscole specifiche delle impostazioni cultura, ordinamento, formattazione e analisi delle regole. Le operazioni sensibili alle impostazioni cultura vengono eseguite nel contesto di impostazioni cultura dichiarate in modo esplicito o nelle impostazioni cultura correnti implicite. I due tipi di operazioni possono produrre risultati molto diversi quando vengono eseguiti sulla stessa stringa.

.NET supporta anche operazioni di stringa linguistica senza distinzione tra impostazioni cultura usando le impostazioni cultura invarianti (CultureInfo.InvariantCulture), che si basa in modo libero sulle impostazioni cultura della lingua inglese indipendente dall'area geografica. A differenza di altre System.Globalization.CultureInfo impostazioni, le impostazioni delle impostazioni cultura invarianti rimangono coerenti in un singolo computer, dal sistema al sistema e tra le versioni di .NET. La cultura invariante può essere vista come una sorta di scatola nera che garantisce la stabilità dei confronti di stringhe e l'ordinamento in tutte le impostazioni cultura.

Importante

Se l'applicazione prende una decisione di sicurezza su un identificatore simbolico, ad esempio un nome di file o una named pipe, o su dati persistenti, ad esempio i dati basati sul testo in un file XML, l'operazione deve usare un confronto ordinale anziché un confronto dipendente dalle impostazioni cultura. Ciò è dovuto al fatto che un confronto dipendente dalle impostazioni cultura può produrre risultati diversi a seconda delle impostazioni cultura, mentre un confronto ordinale dipende esclusivamente dal valore binario dei caratteri confrontati.

Importante

La maggior parte dei metodi che eseguono operazioni stringa include un overload con un parametro di tipo StringComparison, che consente di specificare se il metodo esegue un'operazione ordinale o sensibile alle impostazioni cultura. In generale, è necessario chiamare questo overload per rendere chiara la finalità della chiamata al metodo. Per procedure consigliate e indicazioni sull'uso di operazioni ordinali e sensibili alle impostazioni cultura sulle stringhe, vedere Procedure consigliate per l'uso di stringhe.

Le operazioni per maiuscole e minuscole, analisi e formattazione, confronto e ordinamento e verifica dell'uguaglianza possono essere ordinali o sensibili alle impostazioni cultura. Le sezioni seguenti illustrano ogni categoria di operazione.

Suggerimento

È consigliabile chiamare sempre un overload del metodo che renda chiara la finalità della chiamata al metodo. Ad esempio, anziché chiamare il Compare(String, String) metodo per eseguire un confronto con distinzione delle impostazioni cultura di due stringhe usando le convenzioni delle impostazioni cultura correnti, è necessario chiamare il Compare(String, String, StringComparison) metodo con un valore per StringComparison.CurrentCulture l'argomento comparisonType . Per altre informazioni, vedere Best Practices for Using Strings (Procedure consigliate per l'uso di stringhe).

È possibile scaricare le tabelle di ordinamento, un set di file di testo che contengono informazioni sui pesi dei caratteri usati nelle operazioni di ordinamento e confronto, dai collegamenti seguenti:

Maiuscole/minuscole

Le regole di combinazione di maiuscole e minuscole determinano come modificare la maiuscola di un carattere Unicode; ad esempio, da minuscolo a maiuscolo. Spesso, un'operazione di maiuscole e minuscole viene eseguita prima di un confronto tra stringhe. Ad esempio, una stringa potrebbe essere convertita in maiuscolo in modo che possa essere confrontata con un'altra stringa maiuscola. È possibile convertire i caratteri in una stringa in lettere minuscole chiamando il ToLower metodo o ToLowerInvariant ed è possibile convertirli in lettere maiuscole chiamando il ToUpper metodo o ToUpperInvariant . Inoltre, è possibile usare il TextInfo.ToTitleCase metodo per convertire una stringa in caso di titolo.

Nota

.NET Core in esecuzione solo nei sistemi Linux e macOS: il comportamento delle regole di confronto per le impostazioni cultura C e Posix fa sempre distinzione tra maiuscole e minuscole perché queste impostazioni cultura non usano l'ordine delle regole di confronto Unicode previsto. È consigliabile usare impostazioni cultura diverse da C o Posix per l'esecuzione di operazioni di ordinamento dipendenti dalle impostazioni cultura e senza distinzione tra maiuscole e minuscole.

Le operazioni di maiuscole e minuscole possono essere basate sulle regole delle impostazioni cultura correnti, delle impostazioni cultura specificate o delle impostazioni cultura invarianti. Poiché i mapping dei case possono variare a seconda delle impostazioni cultura usate, il risultato delle operazioni di maiuscole e minuscole può variare in base alle impostazioni cultura. Le differenze effettive nella combinazione di maiuscole e minuscole sono di tre tipi:

  • Differenze nel mapping tra maiuscole e minuscole latine I (U+0049), LETTERE MINUSCOLE LATINE I (U+0069), LETTERA MAIUSCOLA LATINA I CON PUNTO SOPRA (U+0130) e LETTERE MINUSCOLE LATINE I (U+0131). Nelle culture tr-TR (Turco (Turchia)) e az-Latn-AZ (Azerbaigian, Latino) e nelle culture tr, az e az-Latn neutral, l'equivalente minuscolo della LETTERA MAIUSCOLA LATINA I è LATIN SMALL LETTER DOTLESS I e l'equivalente maiuscolo di LATIN SMALL LETTER I è LA LETTERA MAIUSCOLA LATINA I CON PUNTO PRECEDENTE. In tutte le altre impostazioni cultura, incluse le impostazioni cultura invarianti, i caratteri LATIN SMALL LETTER I e LATIN CAPITAL LETTER I sono equivalenti minuscoli e maiuscoli.

    Nell'esempio seguente viene illustrato come un confronto tra stringhe progettato per impedire l'accesso al file system può non riuscire se si basa su un confronto di maiuscole e minuscole sensibili alle impostazioni cultura. Le convenzioni di maiuscole e minuscole delle impostazioni cultura invarianti dovrebbero essere state usate.

    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
    
  • Differenze nei mapping tra le impostazioni cultura invarianti e tutte le altre impostazioni cultura. In questi casi, usando le regole di maiuscole e minuscole delle impostazioni cultura invarianti per modificare un carattere in maiuscolo o minuscolo restituisce lo stesso carattere. Per tutte le altre impostazioni cultura, restituisce un carattere diverso. Alcuni dei caratteri interessati sono elencati nella tabella seguente.

    Carattere Se è stato modificato in Valori restituiti
    SEGNO DI PIGMENTO (U+00B5) Maiuscole GR edizione Enterprise K MAIUSCOLA MU (U+-39C)
    LETTERE MAIUSCOLE LATINE I CON PUNTO SOPRA (U+0130) Minuscole LETTERE MINUSCOLE LATINE I (U+0069)
    ALFABETO LATINO MINUSCOLO SENZA PUNTI (U+0131) Maiuscole LETTERE MAIUSCOLE LATINE I (U+0049)
    ALFABETO LATINO MINUSCOLO LUNGO S (U+017F) Maiuscole LETTERE MAIUSCOLE LATINE S (U+0053)
    MAIUSCOLO LATINO D CON LETTERA MINUSCOLA Z CON CARON (U+01C5) Minuscole ALFABETO LATINO PICCOLO DZ CON CARON (U+01C6)
    COMBINAZIONE DI GR edizione Enterprise K YPOGEGRAMMENI (U+0345) Maiuscole GR edizione Enterprise K MAIUSCOLA IOTA (U+0399)
  • Differenze nei mapping tra maiuscole e minuscole di due lettere nell'intervallo di caratteri ASCII. Nella maggior parte delle impostazioni cultura, una coppia di maiuscole e minuscole a due lettere è uguale alla coppia maiuscola o minuscola equivalente. Ciò non vale per le seguenti coppie di due lettere nelle impostazioni cultura seguenti, perché in ogni caso vengono confrontate con un digrafo:

    • "lJ" e "nJ" nella cultura hr-HR (Croazia)).
    • "cH" nelle impostazioni cultura cs-CSV (Ceco (Repubblica Ceca) e sk-SK (Slovacchia)).
    • "aA" nella cultura da-DK (Danese (Danimarca)).
    • "cS", "dZ", "dZS", "nY", "sZ", "tY" e "zS" nelle impostazioni cultura hu-HU (Ungheria)).
    • "cH" e "lL" nelle impostazioni cultura es-ES_tradnl (Spagnolo (Spagna, Ordinamento tradizionale).)
    • "cH", "gI", "kH", "nG" "nH", "pH", "qU', "tH" e "tR" nella cultura vi-VN (Vietnam)).

    Tuttavia, è insolito riscontrare una situazione in cui un confronto sensibile alle impostazioni cultura di queste coppie crea problemi, perché queste coppie non sono comuni in stringhe fisse o identificatori.

Nell'esempio seguente vengono illustrate alcune delle differenze tra le regole di maiuscole e minuscole tra le impostazioni cultura durante la conversione di stringhe in maiuscolo.

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

Analisi e formattazione

La formattazione e l'analisi sono operazioni inverse. Le regole di formattazione determinano come convertire un valore, ad esempio una data e un'ora o un numero, nella relativa rappresentazione di stringa, mentre le regole di analisi determinano come convertire una rappresentazione di stringa in un valore, ad esempio una data e un'ora. Sia la formattazione che le regole di analisi dipendono dalle convenzioni culturali. Nell'esempio seguente viene illustrata l'ambiguità che può verificarsi durante l'interpretazione di una stringa di data specifica delle impostazioni cultura. Senza conoscere le convenzioni delle impostazioni cultura usate per produrre una stringa di data, non è possibile sapere se 03/01/2011, 3/1/2011 e 01/03/2011 rappresentano il 3 gennaio 2011 o il 1° marzo 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

Analogamente, come illustrato nell'esempio seguente, una singola stringa può produrre date diverse a seconda delle impostazioni cultura le cui convenzioni vengono usate nell'operazione di analisi.

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

Confronto e ordinamento di stringhe

Le convenzioni per il confronto e l'ordinamento delle stringhe variano dalle impostazioni cultura alle impostazioni cultura. Ad esempio, l'ordinamento può essere basato sui fonetici o sulla rappresentazione visiva dei caratteri. Nelle lingue asiatiche, i caratteri sono ordinati in base al tratto e al radicale degli ideogrammi. L'ordinamento dipende anche dalle lingue e dalle impostazioni cultura dell'ordine utilizzate per l'alfabeto. Ad esempio, la lingua danese ha un carattere "Æ" che ordina dopo "Z" nell'alfabeto. Inoltre, i confronti possono essere con distinzione tra maiuscole e minuscole o senza distinzione tra maiuscole e minuscole e regole di maiuscole e minuscole possono variare in base alle impostazioni cultura. Il confronto ordinale, invece, usa i punti di codice Unicode di singoli caratteri in una stringa durante il confronto e l'ordinamento delle stringhe.

Le regole di ordinamento determinano l'ordine alfabetico dei caratteri Unicode e il confronto tra due stringhe. Ad esempio, il String.Compare(String, String, StringComparison) metodo confronta due stringhe in base al StringComparison parametro . Se il valore del parametro è StringComparison.CurrentCulture, il metodo esegue un confronto linguistico che usa le convenzioni delle impostazioni cultura correnti; se il valore del parametro è StringComparison.Ordinal, il metodo esegue un confronto ordinale. Di conseguenza, come illustrato nell'esempio seguente, se le impostazioni cultura correnti sono inglese degli Stati Uniti, la prima chiamata al String.Compare(String, String, StringComparison) metodo (usando un confronto sensibile alle impostazioni cultura) considera "a" minore di "A", ma la seconda chiamata allo stesso metodo (usando il confronto ordinale) considera "a" maggiore di "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 supporta regole di ordinamento ordinale, stringa e parola:

  • Un ordinamento di parole esegue un confronto sensibile alle impostazioni cultura delle stringhe in cui determinati caratteri Unicode non alfanumerici potrebbero avere pesi speciali assegnati. Ad esempio, il trattino (-) potrebbe avere un peso molto piccolo assegnato in modo che "coop" e "co-op" compaiano uno accanto all'altro in un elenco ordinato. Per un elenco dei String metodi che confrontano due stringhe usando le regole di ordinamento delle parole, vedere la sezione Operazioni stringhe per categoria .

  • Un ordinamento di stringa esegue anche un confronto sensibile alle impostazioni cultura. È simile a un ordinamento di parole, ad eccezione del fatto che non esistono casi speciali e tutti i simboli non alfanumerici vengono prima di tutti i caratteri Unicode alfanumerici. È possibile confrontare due stringhe usando le regole di ordinamento delle stringhe chiamando gli overload del CompareInfo.Compare metodo che hanno un options parametro fornito un valore di CompareOptions.StringSort. Si noti che si tratta dell'unico metodo fornito da .NET per confrontare due stringhe usando le regole di ordinamento delle stringhe.

  • Un ordinamento ordinale confronta le stringhe in base al valore numerico di ogni Char oggetto nella stringa. Un confronto ordinale fa automaticamente distinzione tra maiuscole e minuscole perché le versioni minuscole e maiuscole di un carattere hanno punti di codice diversi. Tuttavia, se il caso non è importante, è possibile specificare un confronto ordinale che ignora la distinzione tra maiuscole e minuscole. Equivale a convertire la stringa in maiuscolo usando le impostazioni cultura invarianti e quindi eseguendo un confronto ordinale sul risultato. Per un elenco dei String metodi che confrontano due stringhe usando regole di ordinamento ordinale, vedere la sezione Operazioni stringhe per categoria .

Un confronto con distinzione tra impostazioni cultura è qualsiasi confronto che usa in modo esplicito o implicito un CultureInfo oggetto, incluse le impostazioni cultura invarianti specificate dalla CultureInfo.InvariantCulture proprietà . Le impostazioni cultura implicite sono le impostazioni cultura correnti, specificate dalle Thread.CurrentCulture proprietà e CultureInfo.CurrentCulture . Esiste una notevole variazione nell'ordinamento dei caratteri alfabetici (ovvero i caratteri per i quali la Char.IsLetter proprietà restituisce true) tra le impostazioni cultura. È possibile specificare un confronto sensibile alle impostazioni cultura che usa le convenzioni di impostazioni cultura specifiche fornendo un CultureInfo oggetto a un metodo di confronto di stringhe, ad Compare(String, String, CultureInfo, CompareOptions)esempio . È possibile specificare un confronto sensibile alle impostazioni cultura che utilizza le convenzioni delle impostazioni cultura correnti specificando StringComparison.CurrentCulture, StringComparison.CurrentCultureIgnoreCaseo qualsiasi membro dell'enumerazione CompareOptions diversa da CompareOptions.Ordinal o CompareOptions.OrdinalIgnoreCase a un overload appropriato del Compare metodo . Un confronto con distinzione delle impostazioni cultura è in genere appropriato per l'ordinamento, mentre un confronto ordinale non è. Un confronto ordinale è in genere appropriato per determinare se due stringhe sono uguali ,vale a dire per determinare l'identità, mentre un confronto con distinzione delle impostazioni cultura non è.

Nell'esempio seguente viene illustrata la differenza tra confronto ordinale e sensibile alle impostazioni cultura. Nell'esempio vengono valutate tre stringhe, "Apple", "Æble" e "AEble", usando il confronto ordinale e le convenzioni delle impostazioni cultura da-DK e en-US (ognuna delle quali corrisponde alle impostazioni cultura predefinite al momento della chiamata del Compare metodo). Poiché la lingua danese considera il carattere "Æ" come una singola lettera e la ordina dopo "Z" nell'alfabeto, la stringa "Æble" è maggiore di "Apple". Tuttavia, "Æble" non è considerato equivalente a "AEble", quindi "Æble" è anche maggiore di "AEble". Le impostazioni cultura en-US non includono la lettera "Æ", ma la considera come equivalente a "AE", che spiega perché "Æble" è minore di "Apple" ma uguale a "AEble". Il confronto ordinale, invece, considera "Apple" minore di "Æble" e "Æble" come maggiore di "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

Usare le linee guida generali seguenti per scegliere un metodo di ordinamento o confronto di stringhe appropriato:

  • Se si desidera ordinare le stringhe in base alle impostazioni cultura dell'utente, è consigliabile ordinarle in base alle convenzioni delle impostazioni cultura correnti. Se le impostazioni cultura dell'utente cambiano, anche l'ordine delle stringhe ordinate cambierà di conseguenza. Ad esempio, un'applicazione del thesaurus deve sempre ordinare le parole in base alle impostazioni cultura dell'utente.

  • Se si desidera ordinare le stringhe in base alle convenzioni di impostazioni cultura specifiche, è necessario ordinarle specificando un CultureInfo oggetto che rappresenta tali impostazioni cultura a un metodo di confronto. Ad esempio, in un'applicazione progettata per insegnare agli studenti una determinata lingua, si desidera ordinare stringhe in base alle convenzioni di una delle impostazioni cultura che parlano tale lingua.

  • Se si desidera che l'ordine delle stringhe rimanga invariato tra le impostazioni cultura, è consigliabile ordinarle in base alle convenzioni delle impostazioni cultura invarianti o usare un confronto ordinale. Ad esempio, si usa un ordinamento ordinale per organizzare i nomi di file, processi, mutex o named pipe.

  • Per un confronto che implica una decisione di sicurezza ,ad esempio se un nome utente è valido, è consigliabile eseguire sempre un test ordinale per verificarne l'uguaglianza chiamando un overload del Equals metodo .

Nota

Le regole di ordinamento e di maiuscole e minuscole sensibili alle impostazioni cultura usate nel confronto tra stringhe dipendono dalla versione di .NET. In .NET Core il confronto tra stringhe dipende dalla versione dello standard Unicode supportato dal sistema operativo sottostante. In .NET Framework 4.5 e versioni successive in esecuzione in Windows 8 o versioni successive, l'ordinamento, la combinazione di maiuscole e minuscole, la normalizzazione e le informazioni sui caratteri Unicode sono conformi allo standard Unicode 6.0. In altri sistemi operativi Windows sono conformi allo standard Unicode 5.0.

Per altre informazioni sulle regole di ordinamento ordinale, stringa e parola, vedere l'argomento System.Globalization.CompareOptions . Per consigli aggiuntivi su quando usare ogni regola, vedere Procedure consigliate per l'uso di stringhe.

In genere, non si chiamano metodi di confronto tra stringhe, ad Compare esempio direttamente per determinare l'ordinamento delle stringhe. Al contrario, i metodi di confronto vengono chiamati tramite l'ordinamento di metodi come Array.Sort o List<T>.Sort. Nell'esempio seguente vengono eseguite quattro diverse operazioni di ordinamento (ordinamento delle parole usando le impostazioni cultura correnti, l'ordinamento delle parole usando le impostazioni cultura invarianti, l'ordinamento ordinale e l'ordinamento di stringhe usando le impostazioni cultura invarianti) senza chiamare in modo esplicito un metodo di confronto tra stringhe, anche se specificano il tipo di confronto da usare. Si noti che ogni tipo di ordinamento produce un ordinamento univoco delle stringhe nella relativa matrice.

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

Suggerimento

Internamente, .NET usa chiavi di ordinamento per supportare il confronto di stringhe sensibili alla lingua. A ogni carattere in una stringa vengono date diverse categorie di pesi di ordinamento, tra cui alfabetico, maiuscolo e diacritico. Una chiave di ordinamento, rappresentata dalla SortKey classe , fornisce un repository di questi pesi per una determinata stringa. Se l'app esegue un numero elevato di operazioni di ricerca o ordinamento nello stesso set di stringhe, è possibile migliorarne le prestazioni generando e archiviando le chiavi di ordinamento per tutte le stringhe usate. Quando è necessaria un'operazione di ordinamento o confronto, usare le chiavi di ordinamento anziché le stringhe. Per altre informazioni, vedere la classe SortKey.

Se non si specifica una convenzione di confronto tra stringhe, i metodi di ordinamento, ad Array.Sort(Array) esempio, eseguono un ordinamento con distinzione tra maiuscole e minuscole per le stringhe con distinzione tra maiuscole e minuscole. Nell'esempio seguente viene illustrato come la modifica delle impostazioni cultura correnti influisce sull'ordine delle stringhe ordinate in una matrice. Crea una matrice di tre stringhe. Innanzitutto, imposta la System.Threading.Thread.CurrentThread.CurrentCulture proprietà su en-US e chiama il Array.Sort(Array) metodo . L'ordinamento risultante si basa sulle convenzioni di ordinamento per le impostazioni cultura inglese (Stati Uniti). L'esempio imposta quindi la System.Threading.Thread.CurrentThread.CurrentCulture proprietà su da-DK e chiama di nuovo il Array.Sort metodo . Si noti che l'ordinamento risultante differisce dai risultati en-US perché usa le convenzioni di ordinamento per danese (Danimarca).

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

Avviso

Se lo scopo principale del confronto delle stringhe consiste nel determinare se sono uguali, è necessario chiamare il String.Equals metodo . In genere, è consigliabile usare Equals per eseguire un confronto ordinale. Il String.Compare metodo è destinato principalmente all'ordinamento delle stringhe.

I metodi di ricerca di stringhe, ad esempio String.StartsWith e String.IndexOf, possono anche eseguire confronti di stringhe dipendenti da impostazioni cultura o ordinali. Nell'esempio seguente vengono illustrate le differenze tra i confronti ordinali e sensibili alle impostazioni cultura usando il IndexOf metodo . Una ricerca sensibile alle impostazioni cultura in cui le impostazioni cultura correnti sono inglese (Stati Uniti) considera la sottostringa "oe" in modo che corrisponda alla legatura ""). Poiché un trattino morbido (U+00AD) è un carattere di larghezza zero, la ricerca considera il trattino morbido come equivalente a String.Empty e trova una corrispondenza all'inizio della stringa. Una ricerca ordinale, d'altra parte, non trova una corrispondenza in entrambi i casi.

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

Ricerca in stringhe

I metodi di ricerca di stringhe, ad esempio String.StartsWith e String.IndexOf, possono anche eseguire confronti di stringhe ordinali o sensibili alle impostazioni cultura per determinare se un carattere o una sottostringa viene trovato in una stringa specificata.

I metodi di ricerca nella String classe che cercano un singolo carattere, ad esempio il IndexOf metodo o uno di un set di caratteri, ad esempio il IndexOfAny metodo , eseguono tutte una ricerca ordinale. Per eseguire una ricerca sensibile alle impostazioni cultura per un carattere, è necessario chiamare un CompareInfo metodo come CompareInfo.IndexOf(String, Char) o CompareInfo.LastIndexOf(String, Char). Si noti che i risultati della ricerca di un carattere usando un confronto ordinale e sensibile alle impostazioni cultura possono essere molto diversi. Ad esempio, una ricerca di un carattere Unicode precomposto, ad esempio la legatura "Æ" (U+00C6) potrebbe corrispondere a qualsiasi occorrenza dei relativi componenti nella sequenza corretta, ad esempio "AE" (U+041U+0045), a seconda delle impostazioni cultura. Nell'esempio seguente viene illustrata la differenza tra i metodi e CompareInfo.IndexOf(String, Char) durante la String.IndexOf(Char) ricerca di un singolo carattere. La legatura "æ" (U+00E6) si trova nella stringa "aerea" quando si usano le convenzioni delle impostazioni cultura en-US, ma non quando si usano le convenzioni delle impostazioni cultura da-DK o quando si esegue un confronto ordinale.

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

D'altra parte, String i metodi di classe che cercano una stringa anziché un carattere eseguono una ricerca sensibile alle impostazioni cultura se le opzioni di ricerca non vengono specificate in modo esplicito da un parametro di tipo StringComparison. L'unica eccezione è Contains, che esegue una ricerca ordinale.

Verificare l'uguaglianza

Utilizzare il String.Compare metodo per determinare la relazione di due stringhe nell'ordinamento. In genere, si tratta di un'operazione sensibile alle impostazioni cultura. Al contrario, chiamare il metodo per verificare l'uguaglianza String.Equals . Poiché il test per verificarne l'uguaglianza confronta in genere l'input dell'utente con una stringa nota, ad esempio un nome utente valido, una password o un percorso del file system, è in genere un'operazione ordinale.

Avviso

È possibile verificare l'uguaglianza chiamando il String.Compare metodo e determinando se il valore restituito è zero. Tuttavia, questa pratica non è consigliata. Per determinare se due stringhe sono uguali, è necessario chiamare uno degli overload del String.Equals metodo . L'overload preferito da chiamare è il metodo di istanza Equals(String, StringComparison) o il metodo statico Equals(String, String, StringComparison) , perché entrambi i metodi includono un System.StringComparison parametro che specifica in modo esplicito il tipo di confronto.

Nell'esempio seguente viene illustrato il rischio di eseguire un confronto sensibile alle impostazioni cultura per l'uguaglianza quando è necessario usare un ordinale. In questo caso, lo scopo del codice è impedire l'accesso al file system dagli URL che iniziano con "FILE://" o "file://" eseguendo un confronto senza distinzione tra maiuscole e minuscole dell'inizio di un URL con la stringa "FILE://". Tuttavia, se viene eseguito un confronto con distinzione delle impostazioni cultura usando le impostazioni cultura turche (Turchia) in un URL che inizia con "file://", il confronto per l'uguaglianza ha esito negativo, perché l'equivalente maiuscolo turco di "i" è "İ" anziché "I". Di conseguenza, l'accesso al file system è inavvertitamente consentito. D'altra parte, se viene eseguito un confronto ordinale, il confronto per l'uguaglianza ha esito positivo e l'accesso al file system viene negato.

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.

Normalizzazione

Alcuni caratteri Unicode hanno più rappresentazioni. Ad esempio, uno dei punti di codice seguenti può rappresentare la lettera "ắ":

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

Più rappresentazioni per un singolo carattere complicano la ricerca, l'ordinamento, la corrispondenza e altre operazioni di stringa.

Lo standard Unicode definisce un processo denominato normalizzazione che restituisce una rappresentazione binaria di un carattere Unicode per una delle relative rappresentazioni binarie equivalenti. La normalizzazione può usare diversi algoritmi, detti moduli di normalizzazione, che seguono regole diverse. .NET supporta i moduli di normalizzazione Unicode C, D, KC e KD. Quando le stringhe sono state normalizzate nello stesso formato di normalizzazione, possono essere confrontate usando il confronto ordinale.

Un confronto ordinale è un confronto binario del valore scalare Unicode degli oggetti corrispondenti Char in ogni stringa. La String classe include diversi metodi che possono eseguire un confronto ordinale, tra cui:

È possibile determinare se una stringa è normalizzata nel formato C di normalizzazione chiamando il String.IsNormalized() metodo oppure è possibile chiamare il String.IsNormalized(NormalizationForm) metodo per determinare se una stringa è normalizzata in un formato di normalizzazione specificato. È anche possibile chiamare il String.Normalize() metodo per convertire una stringa in formato C di normalizzazione oppure chiamare il String.Normalize(NormalizationForm) metodo per convertire una stringa in un formato di normalizzazione specificato. Per informazioni dettagliate sulla normalizzazione e il confronto delle stringhe, vedere i Normalize() metodi e Normalize(NormalizationForm) .

Nell'esempio semplice seguente viene illustrata la normalizzazione delle stringhe. Definisce la lettera "ú" in tre modi diversi in tre stringhe diverse e usa un confronto ordinale per determinare che ogni stringa differisce dalle altre due stringhe. Converte quindi ogni stringa nei formati di normalizzazione supportati ed esegue di nuovo un confronto ordinale di ogni stringa in un formato di normalizzazione specificato. In ogni caso, il secondo test di uguaglianza mostra che le stringhe sono uguali.

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

Per altre informazioni sulla normalizzazione e sui moduli di normalizzazione, vedere System.Text.NormalizationForm, nonché l'allegato standard Unicode n. 15: Moduli di normalizzazione Unicode e domande frequenti sulla normalizzazione nel sito Web di unicode.org.

Operazioni stringa per categoria

La String classe fornisce membri per il confronto di stringhe, il test di stringhe per l'uguaglianza, la ricerca di caratteri o sottostringhe in una stringa, la modifica di una stringa, l'estrazione di sottostringhe da una stringa, la combinazione di stringhe, la formattazione dei valori, la copia di una stringa e la normalizzazione di una stringa.

Confrontare le stringhe

È possibile confrontare le stringhe per determinare la posizione relativa nell'ordinamento usando i metodi seguenti String :

  • Compare restituisce un numero intero che indica la relazione di una stringa a una seconda stringa nell'ordinamento.

  • CompareOrdinal restituisce un numero intero che indica la relazione di una stringa a una seconda stringa in base a un confronto dei relativi punti di codice.

  • CompareTo restituisce un numero intero che indica la relazione dell'istanza di stringa corrente a una seconda stringa nell'ordinamento. Il CompareTo(String) metodo fornisce le IComparable implementazioni e IComparable<T> per la String classe .

Testare l'uguaglianza delle stringhe

Chiamare il Equals metodo per determinare se due stringhe sono uguali. L'istanza Equals(String, String, StringComparison) e gli overload statici Equals(String, StringComparison) consentono di specificare se il confronto è sensibile alle impostazioni cultura o ordinale e se la distinzione tra maiuscole e minuscole viene considerata o ignorata. La maggior parte dei test di uguaglianza sono ordinali e i confronti per l'uguaglianza che determinano l'accesso a una risorsa di sistema (ad esempio un oggetto file system) devono essere sempre ordinali.

Trovare caratteri in una stringa

La String classe include due tipi di metodi di ricerca:

Avviso

Se si desidera cercare una stringa per un determinato criterio anziché una sottostringa specifica, è consigliabile usare espressioni regolari. Per altre informazioni, vedere Espressioni regolari .NET.

Modificare una stringa

La String classe include i metodi seguenti che sembrano modificare il valore di una stringa:

  • Insert inserisce una stringa nell'istanza corrente String .

  • PadLeft inserisce una o più occorrenze di un carattere specificato all'inizio di una stringa.

  • PadRight inserisce una o più occorrenze di un carattere specificato alla fine di una stringa.

  • Remove elimina una sottostringa dall'istanza corrente String .

  • Replace sostituisce una sottostringa con un'altra sottostringa nell'istanza corrente String .

  • ToLower e ToLowerInvariant converte tutti i caratteri in una stringa in lettere minuscole.

  • ToUpper e ToUpperInvariant converte tutti i caratteri in una stringa in maiuscolo.

  • Trim rimuove tutte le occorrenze di un carattere dall'inizio e dalla fine di una stringa.

  • TrimEnd rimuove tutte le occorrenze di un carattere dalla fine di una stringa.

  • TrimStart rimuove tutte le occorrenze di un carattere dall'inizio di una stringa.

Importante

Tutti i metodi di modifica delle stringhe restituiscono un nuovo String oggetto. Non modificano il valore dell'istanza corrente.

Estrarre sottostringhe da una stringa

Il String.Split metodo separa una singola stringa in più stringhe. Gli overload del metodo consentono di specificare più delimitatori, di limitare il numero di sottostringhe estratte dal metodo, di tagliare lo spazio vuoto dalle sottostringhe e di specificare se le stringhe vuote (che si verificano quando i delimitatori sono adiacenti) vengono incluse tra le stringhe restituite.

Combinare stringhe

Per la concatenazione di stringhe è possibile usare i metodi seguenti String :

  • Concat combina una o più sottostringhe in una singola stringa.
  • Join concatena una o più sottostringhe in un singolo elemento e aggiunge un separatore tra ogni sottostringa.

Formattare i valori

Il String.Format metodo usa la funzionalità di formattazione composita per sostituire uno o più segnaposto in una stringa con la rappresentazione di stringa di un oggetto o di un valore. Il Format metodo viene spesso usato per eseguire le operazioni seguenti:

  • Per incorporare la rappresentazione di stringa di un valore numerico in una stringa.
  • Per incorporare la rappresentazione di stringa di un valore di data e ora in una stringa.
  • Per incorporare la rappresentazione di stringa di un valore di enumerazione in una stringa.
  • Per incorporare la rappresentazione di stringa di un oggetto che supporta l'interfaccia IFormattable in una stringa.
  • Per giustificare a destra o a sinistra una sottostringa in un campo all'interno di una stringa più grande.

Per informazioni dettagliate sulle operazioni di formattazione ed esempi, vedere il riepilogo dell'overload Format .

Copia una stringa

È possibile chiamare i metodi seguenti String per creare una copia di una stringa:

  • Clone restituisce un riferimento a un oggetto esistente String .
  • Copy crea una copia di una stringa esistente.
  • CopyTo copia una parte di una stringa in una matrice di caratteri.

Normalizzare una stringa

In Unicode un singolo carattere può avere più punti di codice. La normalizzazione converte questi caratteri equivalenti nella stessa rappresentazione binaria. Il String.Normalize metodo esegue la normalizzazione e il String.IsNormalized metodo determina se una stringa è normalizzata.

Per altre informazioni e un esempio, vedere la sezione Normalizzazione più indietro in questo articolo.