Procedure consigliate per l'uso delle stringhe in .NETBest Practices for Using Strings in .NET

.NET offre un ampio supporto per lo sviluppo di applicazioni localizzate e globalizzate e semplifica l'applicazione delle convenzioni relative alle impostazioni cultura correnti o alle impostazioni cultura specifiche quando si eseguono operazioni comuni come l'ordinamento e la visualizzazione delle stringhe..NET provides extensive support for developing localized and globalized applications, and makes it easy to apply the conventions of either the current culture or a specific culture when performing common operations such as sorting and displaying strings. Tuttavia, l'ordinamento o il confronto delle stringhe non è sempre un'operazione con distinzione delle impostazioni cultura.But sorting or comparing strings is not always a culture-sensitive operation. Ad esempio, le stringhe usate internamente da un'applicazione in genere devono essere gestite in modo identico in tutte le impostazioni cultura.For example, strings that are used internally by an application typically should be handled identically across all cultures. Quando i dati di stringa indipendenti dalle impostazioni cultura, ad esempio i tag XML, i tag HTML, i nomi utente, i percorsi di file e i nomi degli oggetti di sistema, vengono interpretati come dati con distinzione delle impostazioni cultura, nel codice dell'applicazione possono verificarsi bug complessi, riduzioni delle prestazioni e, in alcuni casi, problemi di sicurezza.When culturally independent string data, such as XML tags, HTML tags, user names, file paths, and the names of system objects, are interpreted as if they were culture-sensitive, application code can be subject to subtle bugs, poor performance, and, in some cases, security issues.

Questo argomento esamina i metodi di ordinamento, confronto e uso di maiuscole e minuscole nelle stringhe in .NET, offre raccomandazioni per selezionare il metodo di gestione delle stringhe appropriato e fornisce informazioni aggiuntive sui metodi di gestione delle stringhe.This topic examines the string sorting, comparison, and casing methods in .NET, presents recommendations for selecting an appropriate string-handling method, and provides additional information about string-handling methods. Inoltre, esamina come vengono gestiti i file formattati, ad esempio i dati numerici e i dati relativi a data e ora, per la visualizzazione e l'archiviazione.It also examines how formatted data, such as numeric data and date and time data, is handled for display and for storage.

Di seguito sono elencate le diverse sezioni di questo argomento:This topic contains the following sections:

Raccomandazioni per l'uso delle stringheRecommendations for String Usage

Quando si sviluppa con .NET, seguire queste semplici raccomandazione quando si usano le stringhe:When you develop with .NET, follow these simple recommendations when you use strings:

Evitare le operazioni seguenti quando si usano le stringhe:Avoid the following practices when you use strings:

  • Non usare overload che non specificano in modo esplicito o implicito le regole di confronto tra stringhe per le operazioni di stringa.Do not use overloads that do not explicitly or implicitly specify the string comparison rules for string operations.

  • Non usare operazioni di stringa basate su StringComparison.InvariantCulture nella maggior parte dei casi.Do not use string operations based on StringComparison.InvariantCulture in most cases. Una delle poche eccezioni riguarda la conservazione di dati significativi a livello linguistico, ma indipendenti dalle impostazioni cultura.One of the few exceptions is when you are persisting linguistically meaningful but culturally agnostic data.

  • Non usare un overload del metodo String.Compare o CompareTo ed eseguire un test per il valore restituito zero per determinare se due stringhe sono uguali.Do not use an overload of the String.Compare or CompareTo method and test for a return value of zero to determine whether two strings are equal.

  • Non usare la formattazione con distinzione delle impostazioni cultura per conservare i dati numerici o di data e ora in formato stringa.Do not use culture-sensitive formatting to persist numeric data or date and time data in string form.

Torna all'inizioBack to top

Specifica esplicita per il confronto tra stringheSpecifying String Comparisons Explicitly

Molti dei metodi di modifica delle stringhe in .NET sono di tipo overload.Most of the string manipulation methods in .NET are overloaded. In genere, uno o più overload accettano le impostazioni predefinite, mentre altri accettano le impostazioni non predefinite, specificando invece una determinata procedura di confronto o modifica delle stringhe.Typically, one or more overloads accept default settings, whereas others accept no defaults and instead define the precise way in which strings are to be compared or manipulated. La maggior parte dei metodi che non si basano sulle impostazioni predefinite include un parametro di tipo StringComparison, che corrisponde a un'enumerazione che specifica in modo esplicito le regole per il confronto tra stringhe in base alle impostazioni cultura e alle maiuscole e minuscole.Most of the methods that do not rely on defaults include a parameter of type StringComparison, which is an enumeration that explicitly specifies rules for string comparison by culture and case. La tabella seguente descrive i membri dell'enumerazione StringComparison .The following table describes the StringComparison enumeration members.

Membro StringComparisonStringComparison member DescrizioneDescription
CurrentCulture Esegue un confronto con distinzione tra maiuscole e minuscole usando le impostazioni cultura correnti.Performs a case-sensitive comparison using the current culture.
CurrentCultureIgnoreCase Esegue un confronto senza distinzione tra maiuscole e minuscole usando le impostazioni cultura correnti.Performs a case-insensitive comparison using the current culture.
InvariantCulture Esegue un confronto con distinzione tra maiuscole e minuscole usando la lingua inglese.Performs a case-sensitive comparison using the invariant culture.
InvariantCultureIgnoreCase Esegue un confronto senza distinzione tra maiuscole e minuscole usando la lingua inglese.Performs a case-insensitive comparison using the invariant culture.
Ordinal Esegue un confronto ordinale.Performs an ordinal comparison.
OrdinalIgnoreCase Esegue un confronto ordinale senza distinzione tra maiuscole e minuscole.Performs a case-insensitive ordinal comparison.

Ad esempio, il metodo IndexOf , che restituisce l'indice di una sottostringa in un oggetto String che corrisponde a un carattere o a una stringa, ha nove overload:For example, the IndexOf method, which returns the index of a substring in a String object that matches either a character or a string, has nine overloads:

Si consiglia di selezione un overload che non uso i valori predefiniti, per i seguenti motivi:We recommend that you select an overload that does not use default values, for the following reasons:

  • Alcuni overload con parametri predefiniti (quelli che cercano Char nell'istanza della stringa) eseguono un confronto ordinale, mentre altri (quelli che cercano una stringa nell'istanza della stringa) applicano la distinzione delle impostazioni cultura.Some overloads with default parameters (those that search for a Char in the string instance) perform an ordinal comparison, whereas others (those that search for a string in the string instance) are culture-sensitive. È difficile ricordare quale valore predefinito viene usato dai diversi metodi ed è facile confondere gli overload.It is difficult to remember which method uses which default value, and easy to confuse the overloads.

  • Lo scopo del codice basato sui valori predefiniti per le chiamate al metodo non è chiaro.The intent of the code that relies on default values for method calls is not clear. Nell'esempio seguente, che si basa su impostazioni predefinite, è difficile capire se lo sviluppatore intendeva eseguire un confronto ordinale o linguistico tra due stringhe o se la differenza tra maiuscole e minuscole tra protocol e "http" può causare la restituzione di false.In the following example, which relies on defaults, it is difficult to know whether the developer actually intended an ordinal or a linguistic comparison of two strings, or whether a case difference between protocol and "http" might cause the test for equality to return false.

    string protocol = GetProtocol(url);       
    if (String.Equals(protocol, "http")) {
       // ...Code to handle HTTP protocol.
    }
    else {
       throw new InvalidOperationException();
    }
    
    Dim protocol As String = GetProtocol(url)       
    If String.Equals(protocol, "http") Then
       ' ...Code to handle HTTP protocol.
    Else
       Throw New InvalidOperationException()
    End If   
    

In generale, si consiglia di chiamare un metodo non basato sulle impostazioni predefinite perché disambigua lo scopo del codice.In general, we recommend that you call a method that does not rely on defaults, because it makes the intent of the code unambiguous. In questo modo, anche il codice diventa più leggibile ed è più facile eseguirne il debug e la manutenzione.This, in turn, makes the code more readable and easier to debug and maintain. L'esempio seguente riguarda le domande relative all'esempio precedente.The following example addresses the questions raised about the previous example. Viene specificato che viene utilizzato il confronto ordinale e che le differenze tra maiuscole e minuscole vengono ignorate.It makes it clear that ordinal comparison is used and that differences in case are ignored.

string protocol = GetProtocol(url);       
if (String.Equals(protocol, "http", StringComparison.OrdinalIgnoreCase)) {
   // ...Code to handle HTTP protocol.
}
else {
   throw new InvalidOperationException();
}
Dim protocol As String = GetProtocol(url)       
If String.Equals(protocol, "http", StringComparison.OrdinalIgnoreCase) Then
   ' ...Code to handle HTTP protocol.
Else
   Throw New InvalidOperationException()
End If   

Torna all'inizioBack to top

Dettagli sul confronto tra stringheThe Details of String Comparison

Il confronto tra stringhe è la base di molte operazioni relative alle stringhe, in particolare l'ordinamento e il test di uguaglianza.String comparison is the heart of many string-related operations, particularly sorting and testing for equality. L'ordinamento delle stringhe viene eseguito in un modo specifico: se "my" compare prima di "string" in un elenco ordinato di stringhe, nel confronto "my" deve essere minore o uguale a "string".Strings sort in a determined order: If "my" appears before "string" in a sorted list of strings, "my" must compare less than or equal to "string". Inoltre, il confronto definisce implicitamente l'uguaglianza.Additionally, comparison implicitly defines equality. L'operazione di confronto restituisce zero per le stringhe che considera uguali.The comparison operation returns zero for strings it deems equal. In altre parole, nessuna stringa viene considerata minore delle altre.A good interpretation is that neither string is less than the other. Le operazioni più significative relative alle stringhe includono una o più delle seguenti procedure: confronto con un'altra stringa ed esecuzione di un'operazione di ordinamento definita correttamente.Most meaningful operations involving strings include one or both of these procedures: comparing with another string, and executing a well-defined sort operation.

Tuttavia, la valutazione di due stringhe per l'uguaglianza e l'ordinamento non produce un unico risultato corretto; l'esito dipende dai criteri usati per il confronto delle stringhe.However, evaluating two strings for equality or sort order does not yield a single, correct result; the outcome depends on the criteria used to compare the strings. In particolare, i confronti tra stringhe ordinali o basati sulle convenzioni di utilizzo di maiuscole e minuscole e di ordinamento delle impostazioni cultura correnti o della lingua inglese (impostazioni indipendenti dalle impostazioni cultura basate sulla lingua inglese) possono produrre risultati diversi.In particular, string comparisons that are ordinal or that are based on the casing and sorting conventions of the current culture or the invariant culture (a locale-agnostic culture based on the English language) may produce different results.

Confronti tra stringhe che usano le impostazioni cultura correntiString Comparisons that Use the Current Culture

Un criterio prevede l'uso delle convenzioni delle impostazioni cultura correnti quando si confrontano le stringhe.One criterion involves using the conventions of the current culture when comparing strings. I confronti basati sulle impostazioni cultura correnti usano le impostazioni cultura o le impostazioni locali correnti del thread.Comparisons that are based on the current culture use the thread's current culture or locale. Se le impostazioni cultura non vengono impostate dall'utente, vengono usate le impostazioni predefinite della finestra Opzioni internazionali nel Pannello di controllo.If the culture is not set by the user, it defaults to the setting in the Regional Options window in Control Panel. È necessario usare sempre i confronti basati sulle impostazioni cultura correnti quando i dati sono linguisticamente rilevanti e quando riflettono un'interazione utente con distinzione delle impostazioni cultura.You should always use comparisons that are based on the current culture when data is linguistically relevant, and when it reflects culture-sensitive user interaction.

Tuttavia, il comportamento di confronto e di utilizzo di maiuscole e minuscole in .NET cambia quando vengono modificate le impostazioni cultura.However, comparison and casing behavior in .NET changes when the culture changes. Ciò accade quando un'applicazione viene eseguita in un computer con impostazioni cultura diverse da quelle del computer in cui è stata sviluppata oppure quando il thread di esecuzione modifica le proprie impostazioni cultura.This happens when an application executes on a computer that has a different culture than the computer on which the application was developed, or when the executing thread changes its culture. Questo comportamento è intenzionale, tuttavia resta poco chiaro per molti sviluppatori.This behavior is intentional, but it remains non-obvious to many developers. L'esempio seguente illustra le differenze nell'ordinamento tra le impostazioni cultura della lingua inglese per gli Stati Uniti ("en-US") e di quella svedese ("sv-SE").The following example illustrates differences in sort order between the U.S. English ("en-US") and Swedish ("sv-SE") cultures. Si noti che le parole "ångström", "Windows" e "Visual Studio" vengono visualizzate in posizioni diverse nelle matrici di stringhe ordinate.Note that the words "ångström", "Windows", and "Visual Studio" appear in different positions in the sorted string arrays.

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

public class Example
{
   public static void Main()
   {
      string[] values= { "able", "ångström", "apple", "Æble", 
                         "Windows", "Visual Studio" };
      Array.Sort(values);
      DisplayArray(values);

      // Change culture to Swedish (Sweden).
      string originalCulture = CultureInfo.CurrentCulture.Name;
      Thread.CurrentThread.CurrentCulture = new CultureInfo("sv-SE");
      Array.Sort(values);
      DisplayArray(values);

      // Restore the original culture.
      Thread.CurrentThread.CurrentCulture = new CultureInfo(originalCulture);
    }
    
    private static void DisplayArray(string[] values)
    {
      Console.WriteLine("Sorting using the {0} culture:",  
                        CultureInfo.CurrentCulture.Name);
      foreach (string value in values)
         Console.WriteLine("   {0}", value);

      Console.WriteLine();
    }
}
// The example displays the following output:
//       Sorting using the en-US culture:
//          able
//          Æble
//          ångström
//          apple
//          Visual Studio
//          Windows
//       
//       Sorting using the sv-SE culture:
//          able
//          Æble
//          apple
//          Windows
//          Visual Studio
//          ångström
Imports System.Globalization
Imports System.Threading

Module Example
   Public Sub Main()
      Dim values() As String = { "able", "ångström", "apple", _
                                 "Æble", "Windows", "Visual Studio" }
      Array.Sort(values)
      DisplayArray(values)

      ' Change culture to Swedish (Sweden).
      Dim originalCulture As String = CultureInfo.CurrentCulture.Name
      Thread.CurrentThread.CurrentCulture = New CultureInfo("sv-SE")
      Array.Sort(values)
      DisplayArray(values)

      ' Restore the original culture.
      Thread.CurrentThread.CurrentCulture = New CultureInfo(originalCulture)
    End Sub
    
    Private Sub DisplayArray(values() As String)
      Console.WRiteLine("Sorting using the {0} culture:", _ 
                        CultureInfo.CurrentCulture.Name)
      For Each value As String In values
         Console.WriteLine("   {0}", value)
      Next
      Console.WriteLine()   
    End Sub
End Module
' The example displays the following output:
'       Sorting using the en-US culture:
'          able
'          Æble
'          ångström
'          apple
'          Visual Studio
'          Windows
'       
'       Sorting using the sv-SE culture:
'          able
'          Æble
'          apple
'          Windows
'          Visual Studio
'          ångström

I confronti senza distinzione tra maiuscole e minuscole che usano le impostazioni cultura correnti sono uguali a quelli con distinzione delle impostazioni cultura, ma ignorano la distinzione tra maiuscole e minuscole come indicato dalle impostazioni cultura correnti del thread.Case-insensitive comparisons that use the current culture are the same as culture-sensitive comparisons, except that they ignore case as dictated by the thread's current culture. Questo comportamento può manifestarsi anche negli ordinamenti.This behavior may manifest itself in sort orders as well.

I confronti che usano la semantica delle impostazioni cultura correnti sono i confronti predefiniti per i seguenti metodi:Comparisons that use current culture semantics are the default for the following methods:

In ogni caso, si consiglia di chiamare un overload con il parametro StringComparison per rendere chiaro lo scopo della chiamata al metodo.In any case, we recommend that you call an overload that has a StringComparison parameter to make the intent of the method call clear.

È possibile che vengano generati bug complessi e meno complessi quando i dati non linguistici della stringa vengono interpretati linguisticamente oppure quando i dati della stringa di specifiche impostazioni cultura vengono interpretati usando le convenzioni di altre impostazioni cultura.Subtle and not so subtle bugs can emerge when non-linguistic string data is interpreted linguistically, or when string data from a particular culture is interpreted using the conventions of another culture. L'esempio canonico è il problema della I turca.The canonical example is the Turkish-I problem.

Per quasi tutti gli alfabeti latini, incluso l'inglese (Stati Uniti), il carattere "i" (\u0069) corrisponde alla versione minuscola del carattere "I" (\u0049).For nearly all Latin alphabets, including U.S. English, the character "i" (\u0069) is the lowercase version of the character "I" (\u0049). Questa regola di utilizzo di maiuscole e minuscole diventa rapidamente l'impostazione predefinita per chi programma queste impostazioni cultura.This casing rule quickly becomes the default for someone programming in such a culture. Tuttavia, l'alfabeto turco ("tr-TR") include una "I con punto", "İ" (\u0130), che è la versione maiuscola di "i".However, the Turkish ("tr-TR") alphabet includes an "I with a dot" character "İ" (\u0130), which is the capital version of "i". In turco esiste anche un carattere minuscolo "i senza punto", "ı" (\u0131), la cui versione maiuscola è "I".Turkish also includes a lowercase "i without a dot" character, "ı" (\u0131), which capitalizes to "I". Questo comportamento si verifica anche con le impostazioni cultura azera ("az").This behavior occurs in the Azerbaijani ("az") culture as well.

Pertanto, i presupposti relativi all'uso della maiuscola per "i" o della minuscola per "I" non sono validi in tutte le impostazioni cultura.Therefore, assumptions made about capitalizing "i" or lowercasing "I" are not valid among all cultures. Se si usano gli overload predefiniti per le routine di confronto tra stringhe, questi saranno soggetti a variazioni tra le diverse impostazioni cultura.If you use the default overloads for string comparison routines, they will be subject to variance between cultures. Se i dati da confrontare sono di tipo non linguistico, l'uso degli overload predefiniti può produrre risultati indesiderati, come illustrato in questo tentativo di eseguire un confronto senza distinzione tra maiuscole e minuscole delle stringhe "file" e "FILE".If the data to be compared is non-linguistic, using the default overloads can produce undesirable results, as the following attempt to perform a case-insensitive comparison of the strings "file" and "FILE" illustrates.

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

public class Example
{
   public static void Main()
   {
      string fileUrl = "file";
      Thread.CurrentThread.CurrentCulture = new CultureInfo("en-US");
      Console.WriteLine("Culture = {0}",
                        Thread.CurrentThread.CurrentCulture.DisplayName);
      Console.WriteLine("(file == FILE) = {0}", 
                       fileUrl.StartsWith("FILE", true, null));
      Console.WriteLine();
      
      Thread.CurrentThread.CurrentCulture = new CultureInfo("tr-TR");
      Console.WriteLine("Culture = {0}",
                        Thread.CurrentThread.CurrentCulture.DisplayName);
      Console.WriteLine("(file == FILE) = {0}", 
                        fileUrl.StartsWith("FILE", true, null));
   }
}
// The example displays the following output:
//       Culture = English (United States)
//       (file == FILE) = True
//       
//       Culture = Turkish (Turkey)
//       (file == FILE) = False
Imports System.Globalization
Imports System.Threading

Module Example
   Public Sub Main()
      Dim fileUrl = "file"
      Thread.CurrentThread.CurrentCulture = New CultureInfo("en-US")
      Console.WriteLine("Culture = {0}", _
                        Thread.CurrentThread.CurrentCulture.DisplayName)
      Console.WriteLine("(file == FILE) = {0}", _ 
                       fileUrl.StartsWith("FILE", True, Nothing))
      Console.WriteLine()
      
      Thread.CurrentThread.CurrentCulture = New CultureInfo("tr-TR")
      Console.WriteLine("Culture = {0}", _
                        Thread.CurrentThread.CurrentCulture.DisplayName)
      Console.WriteLine("(file == FILE) = {0}", _ 
                        fileUrl.StartsWith("FILE", True, Nothing))
   End Sub
End Module
' The example displays the following output:
'       Culture = English (United States)
'       (file == FILE) = True
'       
'       Culture = Turkish (Turkey)
'       (file == FILE) = False

Questo confronto può causare problemi significativi se le impostazioni cultura vengono usate inavvertitamente in impostazioni relative alla sicurezza, come nel seguente esempio.This comparison could cause significant problems if the culture is inadvertently used in security-sensitive settings, as in the following example. Una chiamata al metodo come IsFileURI("file:") restituisce true, se le impostazioni cultura correnti sono per la lingua inglese (Stati Uniti) oppure false se le impostazioni cultura correnti sono per la lingua turca.A method call such as IsFileURI("file:") returns true if the current culture is U.S. English, but false if the current culture is Turkish. Quindi, nei sistemi turchi, qualcuno potrebbe aggirare le misure di sicurezza che bloccano l'accesso agli URI senza distinzione tra maiuscole e minuscole che iniziano con "FILE:".Thus, on Turkish systems, someone could circumvent security measures that block access to case-insensitive URIs that begin with "FILE:".

public static bool IsFileURI(String path) 
{
   return path.StartsWith("FILE:", true, null);
}
Public Shared Function IsFileURI(path As String) As Boolean 
   Return path.StartsWith("FILE:", True, Nothing)
End Function

In questo caso, poiché "file:" deve essere interpretato come un identificatore non linguistico e senza distinzione delle impostazioni cultura, il codice deve essere scritto come mostrato nell'esempio seguente.In this case, because "file:" is meant to be interpreted as a non-linguistic, culture-insensitive identifier, the code should instead be written as shown in the following example.

public static bool IsFileURI(string path) 
{
   return path.StartsWith("FILE:", StringComparison.OrdinalIgnoreCase);
}
Public Shared Function IsFileURI(path As String) As Boolean 
    Return path.StartsWith("FILE:", StringComparison.OrdinalIgnoreCase)
End Function

Operazioni di stringa ordinaliOrdinal String Operations

La specifica del valore StringComparison.Ordinal o StringComparison.OrdinalIgnoreCase in una chiamata al metodo indica un confronto non linguistico in cui le funzionalità dei linguaggi naturali vengono ignorate.Specifying the StringComparison.Ordinal or StringComparison.OrdinalIgnoreCase value in a method call signifies a non-linguistic comparison in which the features of natural languages are ignored. I metodi richiamati con questi valori StringComparison basano le decisioni relative alle operazioni di stringa su confronti di byte semplici invece che sull'utilizzo di maiuscole e minuscole o di tabelle di equivalenza parametrizzate dalle impostazioni cultura.Methods that are invoked with these StringComparison values base string operation decisions on simple byte comparisons instead of casing or equivalence tables that are parameterized by culture. In molti casi, questo approccio risulta più adatto per l'interpretazione desiderata delle stringhe e rende il codice più veloce e affidabile.In most cases, this approach best fits the intended interpretation of strings while making code faster and more reliable.

I confronti ordinali sono confronti tra stringhe in cui ogni byte di ogni stringa viene confrontato senza interpretazione linguistica, ad esempio "windows" non corrisponde a "Windows".Ordinal comparisons are string comparisons in which each byte of each string is compared without linguistic interpretation; for example, "windows" does not match "Windows". Si tratta essenzialmente di una chiamata alla funzione strcmp di C Runtime.This is essentially a call to the C runtime strcmp function. Usare questo confronto quando il contesto impone l'esatta corrispondenza delle stringhe o richiede un criterio di corrispondenza conservativo.Use this comparison when the context dictates that strings should be matched exactly or demands conservative matching policy. Inoltre, il confronto ordinale è l'operazione di confronto più rapida perché non applica regole linguistiche quando determina un risultato.Additionally, ordinal comparison is the fastest comparison operation because it applies no linguistic rules when determining a result.

Le stringhe in .NET possono contenere caratteri null incorporati.Strings in .NET can contain embedded null characters. Una delle differenze più evidenti tra il confronto ordinale e quello con distinzione delle impostazioni cultura (inclusi i confronti che usano la lingua inglese) riguarda la gestione dei caratteri null incorporati in una stringa.One of the clearest differences between ordinal and culture-sensitive comparison (including comparisons that use the invariant culture) concerns the handling of embedded null characters in a string. Questi caratteri vengono ignorati quando si usano i metodi String.Compare e String.Equals per eseguire confronti con distinzione delle impostazioni cultura (inclusi i confronti che usano la lingua inglese).These characters are ignored when you use the String.Compare and String.Equals methods to perform culture-sensitive comparisons (including comparisons that use the invariant culture). Di conseguenza, nei confronti con distinzione delle impostazioni cultura, le stringhe che contengono caratteri null incorporati e quelle che non li contengono possono essere considerate uguali.As a result, in culture-sensitive comparisons, strings that contain embedded null characters can be considered equal to strings that do not.

Importante

Anche se i metodi di confronto tra stringhe ignorano i caratteri null incorporati, i metodi di ricerca di stringhe come String.Contains, String.EndsWith, String.IndexOf, String.LastIndexOf e String.StartsWith li prendono in considerazione.Although string comparison methods disregard embedded null characters, string search methods such as String.Contains, String.EndsWith, String.IndexOf, String.LastIndexOf, and String.StartsWith do not.

L'esempio successivo esegue un confronto con distinzione delle impostazioni cultura della stringa "Aa" con una stringa simile che contiene diversi caratteri null incorporati tra "A" e "a" e mostra in che modo le due stringhe vengono considerate uguali.The following example performs a culture-sensitive comparison of the string "Aa" with a similar string that contains several embedded null characters between "A" and "a", and shows how the two strings are considered equal.

using System;

public class Example
{
   public static void Main()
   {
      string str1 = "Aa";
      string str2 = "A" + new String('\u0000', 3) + "a";
      Console.WriteLine("Comparing '{0}' ({1}) and '{2}' ({3}):", 
                        str1, ShowBytes(str1), str2, ShowBytes(str2));
      Console.WriteLine("   With String.Compare:");
      Console.WriteLine("      Current Culture: {0}", 
                        String.Compare(str1, str2, StringComparison.CurrentCulture));
      Console.WriteLine("      Invariant Culture: {0}", 
                        String.Compare(str1, str2, StringComparison.InvariantCulture));

      Console.WriteLine("   With String.Equals:");
      Console.WriteLine("      Current Culture: {0}", 
                        String.Equals(str1, str2, StringComparison.CurrentCulture));
      Console.WriteLine("      Invariant Culture: {0}", 
                        String.Equals(str1, str2, StringComparison.InvariantCulture));
   }
   
   private static string ShowBytes(string str)
   {
      string hexString = String.Empty;
      for (int ctr = 0; ctr < str.Length; ctr++)
      {
         string result = String.Empty;
         result = Convert.ToInt32(str[ctr]).ToString("X4");
         result = " " + result.Substring(0,2) + " " + result.Substring(2, 2);
         hexString += result;
      }
      return hexString.Trim();
   }
}
// The example displays the following output:
//    Comparing 'Aa' (00 41 00 61) and 'A   a' (00 41 00 00 00 00 00 00 00 61):
//       With String.Compare:
//          Current Culture: 0
//          Invariant Culture: 0
//       With String.Equals:
//          Current Culture: True
//          Invariant Culture: True
Module Example
   Public Sub Main()
      Dim str1 As String = "Aa"
      Dim str2 As String = "A" + New String(Convert.ToChar(0), 3) + "a"
      Console.WriteLine("Comparing '{0}' ({1}) and '{2}' ({3}):", _
                        str1, ShowBytes(str1), str2, ShowBytes(str2))
      Console.WriteLine("   With String.Compare:")
      Console.WriteLine("      Current Culture: {0}", _
                        String.Compare(str1, str2, StringComparison.CurrentCulture))
      Console.WriteLine("      Invariant Culture: {0}", _
                        String.Compare(str1, str2, StringComparison.InvariantCulture))

      Console.WriteLine("   With String.Equals:")
      Console.WriteLine("      Current Culture: {0}", _
                        String.Equals(str1, str2, StringComparison.CurrentCulture))
      Console.WriteLine("      Invariant Culture: {0}", _
                        String.Equals(str1, str2, StringComparison.InvariantCulture))
   End Sub
   
   Private Function ShowBytes(str As String) As String
      Dim hexString As String = String.Empty
      For ctr As Integer = 0 To str.Length - 1
         Dim result As String = String.Empty
         result = Convert.ToInt32(str.Chars(ctr)).ToString("X4")
         result = " " + result.Substring(0,2) + " " + result.Substring(2, 2)
         hexString += result
      Next
      Return hexString.Trim()
   End Function
End Module

Tuttavia, le stringhe non sono considerate uguali quando si usa il confronto ordinale, come mostrato nell'esempio seguente.However, the strings are not considered equal when you use ordinal comparison, as the following example shows.

Console.WriteLine("Comparing '{0}' ({1}) and '{2}' ({3}):", 
                  str1, ShowBytes(str1), str2, ShowBytes(str2));
Console.WriteLine("   With String.Compare:");
Console.WriteLine("      Ordinal: {0}", 
                  String.Compare(str1, str2, StringComparison.Ordinal));

Console.WriteLine("   With String.Equals:");
Console.WriteLine("      Ordinal: {0}", 
                  String.Equals(str1, str2, StringComparison.Ordinal));
// The example displays the following output:
//    Comparing 'Aa' (00 41 00 61) and 'A   a' (00 41 00 00 00 00 00 00 00 61):
//       With String.Compare:
//          Ordinal: 97
//       With String.Equals:
//          Ordinal: False
Console.WriteLine("Comparing '{0}' ({1}) and '{2}' ({3}):", _
                  str1, ShowBytes(str1), str2, ShowBytes(str2))
Console.WriteLine("   With String.Compare:")
Console.WriteLine("      Ordinal: {0}", _
                  String.Compare(str1, str2, StringComparison.Ordinal))

Console.WriteLine("   With String.Equals:")
Console.WriteLine("      Ordinal: {0}", _
                  String.Equals(str1, str2, StringComparison.Ordinal))
' The example displays the following output:
'    Comparing 'Aa' (00 41 00 61) and 'A   a' (00 41 00 00 00 00 00 00 00 61):
'       With String.Compare:
'          Ordinal: 97
'       With String.Equals:
'          Ordinal: False

I confronti ordinali senza distinzione tra maiuscole e minuscole rappresentano il secondo approccio più conservativo.Case-insensitive ordinal comparisons are the next most conservative approach. Questi confronti ignorano quasi del tutto l'utilizzo di maiuscole e minuscole, ad esempio "windows" corrisponde a "Windows".These comparisons ignore most casing; for example, "windows" matches "Windows". Quando si usano i caratteri ASCII, questo criterio è equivalente a StringComparison.Ordinal, ma ignora il normale utilizzo di maiuscole e minuscole ASCII.When dealing with ASCII characters, this policy is equivalent to StringComparison.Ordinal, except that it ignores the usual ASCII casing. Quindi, qualsiasi carattere in A, Z corrisponde al carattere corrispondente in a,z.Therefore, any character in A, Z matches the corresponding character in a,z. L'utilizzo di maiuscole e minuscole al di fuori dell'intervallo ASCII usa le tabelle in lingua inglese.Casing outside the ASCII range uses the invariant culture's tables. Pertanto, il confronto seguente:Therefore, the following comparison:

String.Compare(strA, strB, StringComparison.OrdinalIgnoreCase);
String.Compare(strA, strB, StringComparison.OrdinalIgnoreCase)

è equivalente (ma più rapido) rispetto al confronto:is equivalent to (but faster than) this comparison:

String.Compare(strA.ToUpperInvariant(), strB.ToUpperInvariant(), 
               StringComparison.Ordinal);
String.Compare(strA.ToUpperInvariant(), strB.ToUpperInvariant(), 
               StringComparison.Ordinal)

Questi confronti sono comunque molto rapidi.These comparisons are still very fast.

Nota

Il comportamento delle stringhe del file system, delle chiavi e dei valori del Registro di sistema e delle variabili di ambiente viene rappresentato in modo efficace da StringComparison.OrdinalIgnoreCase.The string behavior of the file system, registry keys and values, and environment variables is best represented by StringComparison.OrdinalIgnoreCase.

StringComparison.Ordinal e StringComparison.OrdinalIgnoreCase usano direttamente i valori binari e sono i più adatti per la corrispondenza.Both StringComparison.Ordinal and StringComparison.OrdinalIgnoreCase use the binary values directly, and are best suited for matching. Se non si è sicuri delle impostazioni di confronto, usare uno di questi due valori.When you are not sure about your comparison settings, use one of these two values. Tuttavia, poiché eseguono un confronto byte per byte, l'ordinamento non viene eseguito linguisticamente (come in un dizionario inglese), ma in modo binario.However, because they perform a byte-by-byte comparison, they do not sort by a linguistic sort order (like an English dictionary) but by a binary sort order. Se visualizzati dagli utenti, i risultati possono sembrare strani in molti contesti.The results may look odd in most contexts if displayed to users.

La semantica ordinale è l'impostazione predefinita per gli overload String.Equals che non includono un argomento StringComparison (incluso l'operatore di uguaglianza).Ordinal semantics are the default for String.Equals overloads that do not include a StringComparison argument (including the equality operator). In ogni caso, si consiglia di chiamare un overload con un parametro StringComparison .In any case, we recommend that you call an overload that has a StringComparison parameter.

Operazioni di stringa che usano la lingua ingleseString Operations that Use the Invariant Culture

I confronti con la lingua inglese usano la proprietà CompareInfo restituita dalla proprietà statica CultureInfo.InvariantCulture.Comparisons with the invariant culture use the CompareInfo property returned by the static CultureInfo.InvariantCulture property. Questo comportamento è uguale in tutti i sistemi. Converte i caratteri al di fuori dell'intervallo in quelli che considera caratteri equivalenti in lingua inglese.This behavior is the same on all systems; it translates any characters outside its range into what it believes are equivalent invariant characters. Questo criterio può essere utile per gestire il comportamento di un set di stringhe nelle impostazioni cultura, ma spesso produce risultati imprevisti.This policy can be useful for maintaining one set of string behavior across cultures, but it often provides unexpected results.

I confronti senza distinzione tra maiuscole e minuscole con la lingua inglese usano la proprietà statica CompareInfo restituita dalla proprietà statica CultureInfo.InvariantCulture anche per le informazioni sul confronto.Case-insensitive comparisons with the invariant culture use the static CompareInfo property returned by the static CultureInfo.InvariantCulture property for comparison information as well. Le differenze tra maiuscole e minuscole in questi caratteri convertiti vengono ignorate.Any case differences among these translated characters are ignored.

I confronti che usano StringComparison.InvariantCulture e StringComparison.Ordinal funzionano in modo identico nelle stringhe ASCII.Comparisons that use StringComparison.InvariantCulture and StringComparison.Ordinal work identically on ASCII strings. Tuttavia, StringComparison.InvariantCulture prende decisioni linguistiche che potrebbero non essere appropriate per le stringhe che devono essere interpretate come set di byte.However, StringComparison.InvariantCulture makes linguistic decisions that might not be appropriate for strings that have to be interpreted as a set of bytes. L'oggetto CultureInfo.InvariantCulture.CompareInfo fa sì che il metodo Compare interpreti alcuni set di caratteri come equivalenti.The CultureInfo.InvariantCulture.CompareInfo object makes the Compare method interpret certain sets of characters as equivalent. Ad esempio, la seguente equivalenza è valida in lingua inglese:For example, the following equivalence is valid under the invariant culture:

InvariantCulture: a + ̊ = åInvariantCulture: a + ̊ = å

La LETTERA A MINUSCOLA LATINA "a" (\u0061), quando si trova accanto al carattere CERCHIO IN ALTO "+ " ̊" (\u030a), viene interpretata come LETTERA A MINUSCOLA LATINA CON CERCHIO IN ALTO "å" (\u00e5).The LATIN SMALL LETTER A character "a" (\u0061), when it is next to the COMBINING RING ABOVE character "+ " ̊" (\u030a), is interpreted as the LATIN SMALL LETTER A WITH RING ABOVE character "å" (\u00e5). Come mostrato nell'esempio seguente, questo comportamento è diverso dal confronto ordinale.As the following example shows, this behavior differs from ordinal comparison.

string separated = "\u0061\u030a";
string combined = "\u00e5";
      
Console.WriteLine("Equal sort weight of {0} and {1} using InvariantCulture: {2}",
                  separated, combined, 
                  String.Compare(separated, combined, 
                                 StringComparison.InvariantCulture) == 0);

Console.WriteLine("Equal sort weight of {0} and {1} using Ordinal: {2}",
                  separated, combined,
                  String.Compare(separated, combined, 
                                 StringComparison.Ordinal) == 0);
// The example displays the following output:
//    Equal sort weight of a° and å using InvariantCulture: True
//    Equal sort weight of a° and å using Ordinal: False      
Dim separated As String = ChrW(&h61) + ChrW(&h30a)
Dim combined As String = ChrW(&he5)
      
Console.WriteLine("Equal sort weight of {0} and {1} using InvariantCulture: {2}", _
                  separated, combined, _
                  String.Compare(separated, combined, _ 
                                 StringComparison.InvariantCulture) = 0)

Console.WriteLine("Equal sort weight of {0} and {1} using Ordinal: {2}", _
                  separated, combined, _
                  String.Compare(separated, combined, _
                                 StringComparison.Ordinal) = 0)
' The example displays the following output:
'    Equal sort weight of a° and å using InvariantCulture: True
'    Equal sort weight of a° and å using Ordinal: False

Quando si interpretano i nomi di file, i cookie o qualsiasi altro elemento che può contenere un carattere come "å", i confronti ordinali offrono il comportamento più trasparente e appropriato.When interpreting file names, cookies, or anything else where a combination such as "å" can appear, ordinal comparisons still offer the most transparent and fitting behavior.

In realtà la lingua inglese ha poche proprietà che la rendono utile per il confronto.On balance, the invariant culture has very few properties that make it useful for comparison. Esegue il confronto in un modo linguisticamente rilevante, che non assicura un'equivalenza simbolica completa, ma non rappresenta la scelta ottimale per la visualizzazione nelle impostazioni cultura.It does comparison in a linguistically relevant manner, which prevents it from guaranteeing full symbolic equivalence, but it is not the choice for display in any culture. Uno dei pochi motivi per usare StringComparison.InvariantCulture per il confronto riguarda la possibilità di conservare i dati ordinati per visualizzarli in modo identico nelle varie impostazioni cultura.One of the few reasons to use StringComparison.InvariantCulture for comparison is to persist ordered data for a cross-culturally identical display. Ad esempio, se un file di dati di grandi dimensioni che contiene un elenco di identificatori ordinati per la visualizzazione viene associato a un'applicazione, per aggiungere elementi all'elenco è necessario l'inserimento con un ordinamento in lingua inglese.For example, if a large data file that contains a list of sorted identifiers for display accompanies an application, adding to this list would require an insertion with invariant-style sorting.

Torna all'inizioBack to top

Scelta di un membro StringComparison per la chiamata al metodoChoosing a StringComparison Member for Your Method Call

La tabella seguente mostra il mapping da un contesto di stringhe semantico a un membro dell'enumerazione StringComparison .The following table outlines the mapping from semantic string context to a StringComparison enumeration member.

DatiData ComportamentoBehavior System.StringComparison corrispondenteCorresponding System.StringComparison

valorevalue
Identificatori interni con distinzione tra maiuscole e minuscole.Case-sensitive internal identifiers.

Identificatori con distinzione tra maiuscole e minuscole in standard come XML e HTTP.Case-sensitive identifiers in standards such as XML and HTTP.

Impostazioni relative alla sicurezza con distinzione tra maiuscole e minuscole.Case-sensitive security-related settings.
Identificatore non linguistico, con una corrispondenza esatta dei byte.A non-linguistic identifier, where bytes match exactly. Ordinal
Identificatori interni senza distinzione tra maiuscole e minuscole.Case-insensitive internal identifiers.

Identificatori senza distinzione tra maiuscole e minuscole in standard come XML e HTTP.Case-insensitive identifiers in standards such as XML and HTTP.

Percorsi di file.File paths.

Chiavi e valori del Registro di sistema.Registry keys and values.

Variabili di ambiente.Environment variables.

Identificatori di risorse (ad esempio, nomi di handle).Resource identifiers (for example, handle names).

Impostazioni relative alla sicurezza senza distinzione tra maiuscole e minuscole.Case-insensitive security-related settings.
Identificatore non linguistico, in cui la distinzione tra maiuscole e minuscole non è rilevante. In particolare, dati archiviati nella maggior parte dei servizi di sistema Windows.A non-linguistic identifier, where case is irrelevant; especially data stored in most Windows system services. OrdinalIgnoreCase
Alcuni dati persistenti e linguisticamente rilevanti.Some persisted, linguistically relevant data.

Visualizzazione di dati linguistici che richiedono un ordinamento fisso.Display of linguistic data that requires a fixed sort order.
Dati indipendenti dalle impostazioni cultura, ma ancora linguisticamente rilevanti.Culturally agnostic data that still is linguistically relevant. InvariantCulture

oppure-or-

InvariantCultureIgnoreCase
Dati visualizzati dall'utente.Data displayed to the user.

La maggior parte dell'input utente.Most user input.
Dati che richiedono personalizzazioni linguistiche locali.Data that requires local linguistic customs. CurrentCulture

oppure-or-

CurrentCultureIgnoreCase

Torna all'inizioBack to top

Metodi comuni per il confronto tra stringhe in .NETCommon String Comparison Methods in .NET

Le sezioni seguenti descrivono i metodi più comuni per il confronto tra stringhe.The following sections describe the methods that are most commonly used for string comparison.

String.CompareString.Compare

Interpretazione predefinita: StringComparison.CurrentCulture.Default interpretation: StringComparison.CurrentCulture.

Poiché si tratta dell'operazione più importante per l'interpretazione della stringa, tutte le istanze di queste chiamate al metodo devono essere esaminate per determinare se le stringhe devono essere interpretate in base alle impostazioni cultura correnti o devono essere dissociate dalle impostazioni cultura (simbolicamente).As the operation most central to string interpretation, all instances of these method calls should be examined to determine whether strings should be interpreted according to the current culture, or dissociated from the culture (symbolically). In genere, si tratta del secondo caso e deve pertanto essere utilizzato un confronto StringComparison.Ordinal.Typically, it is the latter, and a StringComparison.Ordinal comparison should be used instead.

La classe System.Globalization.CompareInfo, restituita dalla proprietà CultureInfo.CompareInfo, include anche un metodo Compare che fornisce numerose opzioni di corrispondenza (ordinale, con esclusione degli spazi vuoti, con esclusione del tipo Kana e così via) mediante l'enumerazione flag CompareOptions.The System.Globalization.CompareInfo class, which is returned by the CultureInfo.CompareInfo property, also includes a Compare method that provides a large number of matching options (ordinal, ignoring white space, ignoring kana type, and so on) by means of the CompareOptions flag enumeration.

String.CompareToString.CompareTo

Interpretazione predefinita: StringComparison.CurrentCulture.Default interpretation: StringComparison.CurrentCulture.

Questo metodo attualmente non offre un overload che specifica un tipo StringComparison .This method does not currently offer an overload that specifies a StringComparison type. In genere è possibile convertire questo metodo nel formato String.Compare(String, String, StringComparison) consigliato.It is usually possible to convert this method to the recommended String.Compare(String, String, StringComparison) form.

I tipi che implementano le interfacce IComparable e IComparable<T> implementano questo metodo.Types that implement the IComparable and IComparable<T> interfaces implement this method. Poiché non offre l'opzione di un parametro StringComparison , l'implementazione dei tipi spesso lascia specificare all'utente StringComparer nel proprio costruttore.Because it does not offer the option of a StringComparison parameter, implementing types often let the user specify a StringComparer in their constructor. L'esempio seguente definisce una classe FileName il cui costruttore include un parametro StringComparer .The following example defines a FileName class whose class constructor includes a StringComparer parameter. L'oggetto StringComparer viene quindi usato nel metodo FileName.CompareTo .This StringComparer object is then used in the FileName.CompareTo method.

using System;

public class FileName : IComparable
{
   string fname;
   StringComparer comparer; 
   
   public FileName(string name, StringComparer comparer)
   {
      if (String.IsNullOrEmpty(name))
         throw new ArgumentNullException("name");

      this.fname = name;
      
      if (comparer != null)
         this.comparer = comparer;
      else
         this.comparer = StringComparer.OrdinalIgnoreCase;
   }

   public string Name
   {
      get { return fname; }
   }
   
   public int CompareTo(object obj)
   {
      if (obj == null) return 1;

      if (! (obj is FileName))
         return comparer.Compare(this.fname, obj.ToString());
      else
         return comparer.Compare(this.fname, ((FileName) obj).Name);
   }
}
Public Class FileName : Implements IComparable
   Dim fname As String
   Dim comparer As StringComparer 
   
   Public Sub New(name As String, comparer As StringComparer)
      If String.IsNullOrEmpty(name) Then
         Throw New ArgumentNullException("name")
      End If

      Me.fname = name
      
      If comparer IsNot Nothing Then
         Me.comparer = comparer
      Else
         Me.comparer = StringComparer.OrdinalIgnoreCase
      End If      
   End Sub

   Public ReadOnly Property Name As String
      Get
         Return fname
      End Get   
   End Property
   
   Public Function CompareTo(obj As Object) As Integer _
          Implements IComparable.CompareTo
      If obj Is Nothing Then Return 1

      If Not TypeOf obj Is FileName Then
         obj = obj.ToString()
      Else
         obj = CType(obj, FileName).Name
      End If         
      Return comparer.Compare(Me.fname, obj)
   End Function
End Class

String.EqualsString.Equals

Interpretazione predefinita: StringComparison.Ordinal.Default interpretation: StringComparison.Ordinal.

La classe String consente di eseguire un test di uguaglianza chiamando gli overload del metodo Equals dell'istanza o statici oppure usando l'operatore di uguaglianza statico.The String class lets you test for equality by calling either the static or instance Equals method overloads, or by using the static equality operator. Gli overload e l'operatore usano il confronto ordinale per impostazione predefinita.The overloads and operator use ordinal comparison by default. Tuttavia, si consiglia di chiamare comunque un overload che specifichi esplicitamente il tipo StringComparison anche se si vuole eseguire un confronto ordinale; questo semplifica la ricerca di codice per una determinata interpretazione della stringa.However, we still recommend that you call an overload that explicitly specifies the StringComparison type even if you want to perform an ordinal comparison; this makes it easier to search code for a certain string interpretation.

String.ToUpper e String.ToLowerString.ToUpper and String.ToLower

Interpretazione predefinita: StringComparison.CurrentCulture.Default interpretation: StringComparison.CurrentCulture.

Prestare attenzione quando si usano questi metodi perché l'utilizzo forzato di maiuscole o minuscole in una stringa è una procedura usata spesso come normalizzazione minore per confrontare stringhe indipendentemente dalla distinzione tra maiuscole e minuscole.You should be careful when you use these methods, because forcing a string to a uppercase or lowercase is often used as a small normalization for comparing strings regardless of case. In questo caso, valutare l'uso di un confronto senza distinzione tra maiuscole e minuscole.If so, consider using a case-insensitive comparison.

Sono disponibili anche i metodi String.ToUpperInvariant e String.ToLowerInvariant.The String.ToUpperInvariant and String.ToLowerInvariant methods are also available. ToUpperInvariant è la modalità standard di normalizzazione dei caratteri maiuscoli e minuscoli.ToUpperInvariant is the standard way to normalize case. A livello di comportamento, i confronti eseguiti con StringComparison.OrdinalIgnoreCase corrispondono alla composizione di due chiamate: la chiamata a ToUpperInvariant in entrambi gli argomenti di stringa e l'esecuzione di un confronto con StringComparison.Ordinal.Comparisons made using StringComparison.OrdinalIgnoreCase are behaviorally the composition of two calls: calling ToUpperInvariant on both string arguments, and doing a comparison using StringComparison.Ordinal.

Sono disponibili anche overload per la conversione in maiuscole e minuscole in determinate impostazioni cultura, passando un oggetto CultureInfo che rappresenta le specifiche impostazioni cultura al metodo.Overloads are also available for converting to uppercase and lowercase in a specific culture, by passing a CultureInfo object that represents that culture to the method.

Char.ToUpper e Char.ToLowerChar.ToUpper and Char.ToLower

Interpretazione predefinita: StringComparison.CurrentCulture.Default interpretation: StringComparison.CurrentCulture.

Questi metodi funzionano in modo simile ai metodi String.ToUpper e String.ToLower descritti nella sezione precedente.These methods work similarly to the String.ToUpper and String.ToLower methods described in the previous section.

String.StartsWith e String.EndsWithString.StartsWith and String.EndsWith

Interpretazione predefinita: StringComparison.CurrentCulture.Default interpretation: StringComparison.CurrentCulture.

Per impostazione predefinita, entrambi i metodi eseguono un confronto con distinzione delle impostazioni cultura.By default, both of these methods perform a culture-sensitive comparison.

String.IndexOf e String.LastIndexOfString.IndexOf and String.LastIndexOf

Interpretazione predefinita: StringComparison.CurrentCulture.Default interpretation: StringComparison.CurrentCulture.

La modalità di esecuzione dei confronti con gli overload predefiniti di questi metodi manca di coerenza.There is a lack of consistency in how the default overloads of these methods perform comparisons. Tutti i metodi String.IndexOf e String.LastIndexOf che includono un parametro Char eseguono un confronto ordinale, ma i metodi predefiniti String.IndexOf e String.LastIndexOf che includono un parametro String eseguono un confronto con distinzione delle impostazioni cultura.All String.IndexOf and String.LastIndexOf methods that include a Char parameter perform an ordinal comparison, but the default String.IndexOf and String.LastIndexOf methods that include a String parameter perform a culture-sensitive comparison.

Se si chiama il metodo String.IndexOf(String) o String.LastIndexOf(String) e si passa una stringa da individuare nell'istanza corrente, si consiglia di chiamare un overload che specifichi esplicitamente il tipo StringComparison.If you call the String.IndexOf(String) or String.LastIndexOf(String) method and pass it a string to locate in the current instance, we recommend that you call an overload that explicitly specifies the StringComparison type. Gli overload che includono un argomento Char non consentono di specificare un tipo StringComparison .The overloads that include a Char argument do not allow you to specify a StringComparison type.

Torna all'inizioBack to top

Metodi che eseguono indirettamente il confronto tra stringheMethods that Perform String Comparison Indirectly

Alcuni metodi non di tipo stringa in cui il confronto tra stringhe rappresenta l'operazione più importante usano il tipo StringComparer .Some non-string methods that have string comparison as a central operation use the StringComparer type. La classe StringComparer include sei proprietà statiche che restituiscono istanze StringComparer i cui metodi StringComparer.Compare eseguono i tipi di confronto tra stringhe seguenti:The StringComparer class includes six static properties that return StringComparer instances whose StringComparer.Compare methods perform the following types of string comparisons:

Array.Sort e Array.BinarySearchArray.Sort and Array.BinarySearch

Interpretazione predefinita: StringComparison.CurrentCulture.Default interpretation: StringComparison.CurrentCulture.

Quando si archiviano dati in una raccolta o si leggono dati persistenti da un file o da un database nella raccolta, la modifica delle impostazioni cultura correnti può invalidare le invarianti nella raccolta.When you store any data in a collection, or read persisted data from a file or database into a collection, switching the current culture can invalidate the invariants in the collection. Il metodo Array.BinarySearch presuppone che gli elementi nella matrice da cercare siano già ordinati.The Array.BinarySearch method assumes that the elements in the array to be searched are already sorted. Per ordinare qualsiasi elemento di tipo stringa nella matrice, il metodo Array.Sort chiama il metodo String.Compare per ordinare i singoli elementi.To sort any string element in the array, the Array.Sort method calls the String.Compare method to order individual elements. L'uso di un operatore di confronto con distinzione delle impostazioni cultura può essere pericoloso se le impostazioni cultura vengono modificate tra l'ordinamento della matrice e la ricerca dei contenuti.Using a culture-sensitive comparer can be dangerous if the culture changes between the time that the array is sorted and its contents are searched. Nel codice seguente, ad esempio, le operazioni di archiviazione e recupero vengono eseguite sull'operatore di confronto fornito in modo implicito dalla proprietà Thread.CurrentThread.CurrentCulture .For example, in the following code, storage and retrieval operate on the comparer that is provided implicitly by the Thread.CurrentThread.CurrentCulture property. Se le impostazioni cultura possono cambiare tra le chiamate a StoreNames e DoesNameExiste, in particolare, se il contenuto della matrice viene conservato tra le due chiamate al metodo, è possibile che la ricerca binaria non riesca.If the culture can change between the calls to StoreNames and DoesNameExist, and especially if the array contents are persisted somewhere between the two method calls, the binary search may fail.

// Incorrect.
string []storedNames;

public void StoreNames(string [] names)
{
   int index = 0;
   storedNames = new string[names.Length];

   foreach (string name in names)
   {
      this.storedNames[index++] = name;
   }

   Array.Sort(names); // Line A.
}

public bool DoesNameExist(string name)
{
   return (Array.BinarySearch(this.storedNames, name) >= 0);  // Line B.
}
' Incorrect.
Dim storedNames() As String

Public Sub StoreNames(names() As String)
   Dim index As Integer = 0
   ReDim storedNames(names.Length - 1)
   
   For Each name As String In names
      Me.storedNames(index) = name
      index+= 1
   Next
   
   Array.Sort(names)          ' Line A.
End Sub

Public Function DoesNameExist(name As String) As Boolean
   Return Array.BinarySearch(Me.storedNames, name) >= 0      ' Line B.
End Function

L'esempio seguente mostra una variazione consigliata che usa lo stesso metodo di confronto ordinale (senza distinzione delle impostazioni cultura) sia per l'ordinamento che per la ricerca nella matrice.A recommended variation appears in the following example, which uses the same ordinal (culture-insensitive) comparison method both to sort and to search the array. Il codice modificato si riflette nelle righe identificate con Line A e Line B nei due esempi.The change code is reflected in the lines labeled Line A and Line B in the two examples.

// Correct.
string []storedNames;

public void StoreNames(string [] names)
{
   int index = 0;
   storedNames = new string[names.Length];

   foreach (string name in names)
   {
      this.storedNames[index++] = name;
   }

   Array.Sort(names, StringComparer.Ordinal);  // Line A.
}

public bool DoesNameExist(string name)
{
   return (Array.BinarySearch(this.storedNames, name, StringComparer.Ordinal) >= 0);  // Line B.
}
' Correct.
Dim storedNames() As String

Public Sub StoreNames(names() As String)
   Dim index As Integer = 0
   ReDim storedNames(names.Length - 1)
   
   For Each name As String In names
      Me.storedNames(index) = name
      index+= 1
   Next
   
   Array.Sort(names, StringComparer.Ordinal)           ' Line A.
End Sub

Public Function DoesNameExist(name As String) As Boolean
   Return Array.BinarySearch(Me.storedNames, name, StringComparer.Ordinal) >= 0      ' Line B.
End Function

Se i dati vengono conservati e spostati nelle impostazioni cultura e l'ordinamento viene usato per presentare i dati all'utente, potrebbe esser opportuno usare StringComparison.InvariantCulture, che garantisce un output utente migliore dal punto di vista linguistico ma non viene interessato dalle modifiche nelle impostazioni cultura.If this data is persisted and moved across cultures, and sorting is used to present this data to the user, you might consider using StringComparison.InvariantCulture, which operates linguistically for better user output but is unaffected by changes in culture. L'esempio seguente modifica i due esempi precedenti per usare la lingua inglese per l'ordinamento e la ricerca della matrice.The following example modifies the two previous examples to use the invariant culture for sorting and searching the array.

// Correct.
string []storedNames;

public void StoreNames(string [] names)
{
   int index = 0;
   storedNames = new string[names.Length];

   foreach (string name in names)
   {
      this.storedNames[index++] = name;
   }

   Array.Sort(names, StringComparer.InvariantCulture);  // Line A.
}

public bool DoesNameExist(string name)
{
   return (Array.BinarySearch(this.storedNames, name, StringComparer.InvariantCulture) >= 0);  // Line B.
}
' Correct.
Dim storedNames() As String

Public Sub StoreNames(names() As String)
   Dim index As Integer = 0
   ReDim storedNames(names.Length - 1)
   
   For Each name As String In names
      Me.storedNames(index) = name
      index+= 1
   Next
   
   Array.Sort(names, StringComparer.InvariantCulture)           ' Line A.
End Sub

Public Function DoesNameExist(name As String) As Boolean
   Return Array.BinarySearch(Me.storedNames, name, StringComparer.InvariantCulture) >= 0      ' Line B.
End Function

Esempio di raccolte: costruttore HashtableCollections Example: Hashtable Constructor

L'esecuzione dell'hashing nelle stringhe fornisce un secondo esempio di operazione interessata dal modo in cui vengono confrontate le stringhe.Hashing strings provides a second example of an operation that is affected by the way in which strings are compared.

L'esempio seguente crea un'istanza di un oggetto Hashtable passando l'oggetto StringComparer restituito dalla proprietà StringComparer.OrdinalIgnoreCase.The following example instantiates a Hashtable object by passing it the StringComparer object that is returned by the StringComparer.OrdinalIgnoreCase property. Poiché una classe StringComparer derivata da StringComparer implementa l'interfaccia IEqualityComparer , il metodo GetHashCode viene usato per calcolare il codice hash delle stringhe nella tabella hash.Because a class StringComparer that is derived from StringComparer implements the IEqualityComparer interface, its GetHashCode method is used to compute the hash code of strings in the hash table.

const int initialTableCapacity = 100;
Hashtable h;

public void PopulateFileTable(string directory)
{
   h = new Hashtable(initialTableCapacity, 
                     StringComparer.OrdinalIgnoreCase);
         
   foreach (string file in Directory.GetFiles(directory))
         h.Add(file, File.GetCreationTime(file));
}

public void PrintCreationTime(string targetFile)
{
   Object dt = h[targetFile];
   if (dt != null)
   {
      Console.WriteLine("File {0} was created at time {1}.",
         targetFile, 
         (DateTime) dt);
   }
   else
   {
      Console.WriteLine("File {0} does not exist.", targetFile);
   }
}
Const initialTableCapacity As Integer = 100
Dim h As Hashtable

Public Sub PopulateFileTable(dir As String)
   h = New Hashtable(initialTableCapacity, _
                     StringComparer.OrdinalIgnoreCase)
                     
   For Each filename As String In Directory.GetFiles(dir)
      h.Add(filename, File.GetCreationTime(filename))
   Next                        
End Sub

Public Sub PrintCreationTime(targetFile As String)
   Dim dt As Object = h(targetFile)
   If dt IsNot Nothing Then
      Console.WriteLine("File {0} was created at {1}.", _
         targetFile, _
         CDate(dt))
   Else
      Console.WriteLine("File {0} does not exist.", targetFile)
   End If
End Sub  

Torna all'inizioBack to top

Visualizzazione e conservazione dei dati formattatiDisplaying and Persisting Formatted Data

Quando si consente agli utenti di visualizzare dati non di tipo stringa, come numeri e date e ore, formattarli usando le impostazioni cultura dell'utente.When you display non-string data such as numbers and dates and times to users, format them by using the user's cultural settings. Per impostazione predefinita, il metodo String.Format e i metodi ToString dei tipi numerici e dei tipi data e ora usano le impostazioni cultura del thread corrente per le operazioni di formattazione.By default, the String.Format method and the ToString methods of the numeric types and the date and time types use the current thread culture for formatting operations. Per specificare esplicitamente che il metodo di formattazione deve usare le impostazioni cultura correnti, è possibile chiamare un overload di un metodo di formattazione con un parametro provider, ad esempio String.Format(IFormatProvider, String, Object[]) o DateTime.ToString(IFormatProvider), e passare la proprietà CultureInfo.CurrentCulture.To explicitly specify that the formatting method should use the current culture, you can call an overload of a formatting method that has a provider parameter, such as String.Format(IFormatProvider, String, Object[]) or DateTime.ToString(IFormatProvider), and pass it the CultureInfo.CurrentCulture property.

È possibile conservare i dati non di tipo stringa come dati binari o formattati.You can persist non-string data either as binary data or as formatted data. Se si sceglie di salvarli come dati formattati, è necessario chiamare un overload del metodo di formattazione che include un parametro provider e passare la proprietà CultureInfo.InvariantCulture.If you choose to save it as formatted data, you should call a formatting method overload that includes a provider parameter and pass it the CultureInfo.InvariantCulture property. La lingua inglese fornisce un formato coerente per i dati formattati, indipendente dalle impostazioni cultura e dal computer.The invariant culture provides a consistent format for formatted data that is independent of culture and machine. Al contrario, conservare i dati formattati con impostazioni cultura diverse dalla lingua inglese presenta diverse limitazioni:In contrast, persisting data that is formatted by using cultures other than the invariant culture has a number of limitations:

  • È probabile che i dati non saranno utilizzabili se vengono recuperati in un sistema con impostazioni cultura diverse oppure se l'utente del sistema corrente modifica le impostazioni cultura correnti e prova a recuperare i dati.The data is likely to be unusable if it is retrieved on a system that has a different culture, or if the user of the current system changes the current culture and tries to retrieve the data.

  • Le proprietà delle impostazioni cultura in uno specifico computer possono essere diverse rispetto ai valori standard.The properties of a culture on a specific computer can differ from standard values. Un utente può personalizzare in qualsiasi momento le impostazioni di visualizzazione con distinzione delle impostazioni cultura.At any time, a user can customize culture-sensitive display settings. Per questo motivo, i dati formattati salvati in un sistema potrebbero non essere leggibili dopo che un utente personalizza le impostazioni cultura.Because of this, formatted data that is saved on a system may not be readable after the user customizes cultural settings. La portabilità dei dati formattati tra i vari computer potrebbe risultare ancora più limitata.The portability of formatted data across computers is likely to be even more limited.

  • Gli standard internazionali, regionali o nazionali che regolano la formattazione dei numeri o delle date e delle ore cambiano nel tempo e queste modifiche vengono incorporate negli aggiornamenti del sistema operativo Windows.International, regional, or national standards that govern the formatting of numbers or dates and times change over time, and these changes are incorporated into Windows operating system updates. Quando le convenzioni di formattazione vengono modificate, i dati formattati con le convenzioni precedenti possono diventare illeggibili.When formatting conventions change, data that was formatted by using the previous conventions may become unreadable.

L'esempio seguente illustra la limitazione della portabilità causata dall'uso della formattazione con distinzione delle impostazioni cultura per la persistenza dei dati.The following example illustrates the limited portability that results from using culture-sensitive formatting to persist data. L'esempio salva una matrice di valori di data e ora in un file.The example saves an array of date and time values to a file. Questi vengono formattati usando le convenzioni delle impostazioni cultura per la lingua inglese (Stati Uniti) .These are formatted by using the conventions of the English (United States) culture. Quando l'applicazione modifica le impostazioni cultura del thread corrente in francese (Svizzera), tenta di leggere i valori salvati usando le convenzioni di formattazione delle impostazioni cultura correnti.After the application changes the current thread culture to French (Switzerland), it tries to read the saved values by using the formatting conventions of the current culture. Il tentativo di lettura di due elementi di dati genera un'eccezione FormatException , quindi la matrice di date conterrà due elementi non corretti uguali a MinValue.The attempt to read two of the data items throws a FormatException exception, and the array of dates now contains two incorrect elements that are equal to MinValue.

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

public class Example
{
   private static string filename = @".\dates.dat";

   public static void Main()
   {
      DateTime[] dates = { new DateTime(1758, 5, 6, 21, 26, 0), 
                           new DateTime(1818, 5, 5, 7, 19, 0), 
                           new DateTime(1870, 4, 22, 23, 54, 0),  
                           new DateTime(1890, 9, 8, 6, 47, 0), 
                           new DateTime(1905, 2, 18, 15, 12, 0) }; 
      // Write the data to a file using the current culture.
      WriteData(dates);
      // Change the current culture.
      Thread.CurrentThread.CurrentCulture = CultureInfo.CreateSpecificCulture("fr-CH");
      // Read the data using the current culture.
      DateTime[] newDates = ReadData();
      foreach (var newDate in newDates)
         Console.WriteLine(newDate.ToString("g"));
   }
   
   private static void WriteData(DateTime[] dates) 
   {
      StreamWriter sw = new StreamWriter(filename, false, Encoding.UTF8);    
      for (int ctr = 0; ctr < dates.Length; ctr++) {
         sw.Write("{0}", dates[ctr].ToString("g", CultureInfo.CurrentCulture));
         if (ctr < dates.Length - 1) sw.Write("|");   
      }      
      sw.Close();
   }
   
   private static DateTime[] ReadData() 
   {
      bool exceptionOccurred = false;
           
      // Read file contents as a single string, then split it.
      StreamReader sr = new StreamReader(filename, Encoding.UTF8);
      string output = sr.ReadToEnd();
      sr.Close();   

      string[] values = output.Split( new char[] { '|' } );
      DateTime[] newDates = new DateTime[values.Length]; 
      for (int ctr = 0; ctr < values.Length; ctr++) {
         try {
            newDates[ctr] = DateTime.Parse(values[ctr], CultureInfo.CurrentCulture);
         }
         catch (FormatException) {
            Console.WriteLine("Failed to parse {0}", values[ctr]);
            exceptionOccurred = true;
         }
      }      
      if (exceptionOccurred) Console.WriteLine();
      return newDates;
   }
}
// The example displays the following output:
//       Failed to parse 4/22/1870 11:54 PM
//       Failed to parse 2/18/1905 3:12 PM
//       
//       05.06.1758 21:26
//       05.05.1818 07:19
//       01.01.0001 00:00
//       09.08.1890 06:47
//       01.01.0001 00:00
//       01.01.0001 00:00
Imports System.Globalization
Imports System.IO
Imports System.Text
Imports System.Threading

Module Example
   Private filename As String = ".\dates.dat"
   
   Public Sub Main()
      Dim dates() As Date = { #5/6/1758 9:26PM#, #5/5/1818 7:19AM#, _ 
                              #4/22/1870 11:54PM#, #9/8/1890 6:47AM#, _ 
                              #2/18/1905 3:12PM# }
      ' Write the data to a file using the current culture.
      WriteData(dates)
      ' Change the current culture.
      Thread.CurrentThread.CurrentCulture = CultureInfo.CreateSpecificCulture("fr-CH")
      ' Read the data using the current culture.
      Dim newDates() As Date = ReadData()
      For Each newDate In newDates
         Console.WriteLine(newDate.ToString("g"))
      Next
   End Sub
   
   Private Sub WriteData(dates() As Date)
      Dim sw As New StreamWriter(filename, False, Encoding.Utf8)    
      For ctr As Integer = 0 To dates.Length - 1
         sw.Write("{0}", dates(ctr).ToString("g", CultureInfo.CurrentCulture))
         If ctr < dates.Length - 1 Then sw.Write("|")   
      Next      
      sw.Close()
   End Sub
   
   Private Function ReadData() As Date()
      Dim exceptionOccurred As Boolean = False
           
      ' Read file contents as a single string, then split it.
      Dim sr As New StreamReader(filename, Encoding.Utf8)
      Dim output As String = sr.ReadToEnd()
      sr.Close()   

      Dim values() As String = output.Split( {"|"c } )
      Dim newDates(values.Length - 1) As Date 
      For ctr As Integer = 0 To values.Length - 1
         Try
            newDates(ctr) = DateTime.Parse(values(ctr), CultureInfo.CurrentCulture)
         Catch e As FormatException
            Console.WriteLine("Failed to parse {0}", values(ctr))
            exceptionOccurred = True
         End Try
      Next      
      If exceptionOccurred Then Console.WriteLine()
      Return newDates
   End Function
End Module
' The example displays the following output:
'       Failed to parse 4/22/1870 11:54 PM
'       Failed to parse 2/18/1905 3:12 PM
'       
'       05.06.1758 21:26
'       05.05.1818 07:19
'       01.01.0001 00:00
'       09.08.1890 06:47
'       01.01.0001 00:00
'       01.01.0001 00:00
'

Tuttavia, se si sostituisce la proprietà CultureInfo.CurrentCulture con CultureInfo.InvariantCulture nelle chiamate a DateTime.ToString(String, IFormatProvider) e a DateTime.Parse(String, IFormatProvider), i dati persistenti di data e ora vengono ripristinati correttamente, come illustrato nell'output riportato di seguito.However, if you replace the CultureInfo.CurrentCulture property with CultureInfo.InvariantCulture in the calls to DateTime.ToString(String, IFormatProvider) and DateTime.Parse(String, IFormatProvider), the persisted date and time data is successfully restored, as the following output shows.

06.05.1758 21:26  
05.05.1818 07:19  
22.04.1870 23:54  
08.09.1890 06:47  
18.02.1905 15:12  

Vedere ancheSee Also

Modifica di stringheManipulating Strings