Share via


Procedura: confrontare stringhe (Guida per programmatori C#)

Aggiornamento: Luglio 2008

Quando si confrontano stringhe, si produce un risultato che indica che una stringa è maggiore o minore dell'altra o che le due stringhe sono uguali. Le regole in base alle quali viene determinato il risultato sono diverse a seconda che si esegua un confronto ordinale o un confronto dipendente dalle impostazioni cultura. È importante utilizzare il tipo corretto di confronto per l'attività specifica.

Utilizzare confronti ordinali di base quando è necessario confrontare o ordinare i valori di due stringhe indipendentemente dalle convenzioni linguistiche. Un confronto ordinale di base (Ordinal) distingue tra maiuscole e minuscole, cioè le due stringhe devono corrispondere esattamente carattere per carattere: "file" non equivale a "FILE" né a "File". Una variazione utilizzata frequentemente è OrdinalIgnoreCase, che consente la corrispondenza di "file", "FILE" e "File". StringComparison.OrdinalIgnoreCase spesso è utilizzato per confrontare nomi di file, percorsi, percorsi di rete e qualsiasi altra stringa il cui valore non cambia in base alle impostazioni locali del computer dell'utente.

I confronti dipendenti dalle impostazioni cultura sono utilizzati in genere per confrontare e ordinare stringhe che sono input di utenti finali, perché i caratteri e le convenzioni di ordinamento di queste stringhe possono variare a seconda delle impostazioni locali del computer dell'utente. Anche stringhe che contengono caratteri identici potrebbero essere ordinate in modo diverso a seconda delle impostazioni cultura del thread corrente.

Nota:

Quando si confrontano stringhe, è opportuno utilizzare i metodi che specificano in modo esplicito il tipo di confronto che si intende eseguire. In questo modo il codice può essere gestito e letto con maggiore facilità. Quando possibile, utilizzare gli overload dei metodi delle classi System.String e System.Array che accettano un parametro di enumerazione StringComparison, in modo da poter specificare il tipo di confronto da eseguire. È meglio evitare l'utilizzo degli operatori == e != quando si confrontano stringhe. Inoltre, evitare di utilizzare i metodi di istanza String.CompareTo perché nessuno degli overload accetta StringComparison.

Esempio

Nell'esempio seguente viene mostrato come confrontare correttamente stringhe i cui valori non cambiano in base alle impostazioni locali del computer dell'utente. Viene inoltre illustrata la funzionalità inserimento di stringa di C#. Quando un programma dichiara due o più variabili di stringa identiche, il compilatore le archivia tutte nella stessa posizione. Chiamando il metodo ReferenceEquals, è possibile vedere che le due stringhe si riferiscono allo stesso oggetto in memoria. Utilizzare il metodo String.Copy per evitare l'inserimento di stringa, come mostrato nell'esempio.

// Internal strings that will never be localized.
string root = @"C:\users";
string root2 = @"C:\Users";

// Use the overload of the Equals method that specifies a StringComparison.
// Ordinal is the fastest way to compare two strings.
bool result = root.Equals(root2, StringComparison.Ordinal);

Console.WriteLine("Ordinal comparison: {0} and {1} are {2}", root, root2,
                    result ? "equal." : "not equal.");

// To ignore case means "user" equals "User". This is the same as using
// String.ToUpperInvariant on each string and then performing an ordinal comparison.
result = root.Equals(root2, StringComparison.OrdinalIgnoreCase);
Console.WriteLine("Ordinal ignore case: {0} and {1} are {2}", root, root2,
                     result ? "equal." : "not equal.");

// A static method is also available.
bool areEqual = String.Equals(root, root2, StringComparison.Ordinal);


// String interning. Are these really two distinct objects?
string a = "The computer ate my source code.";
string b = "The computer ate my source code.";

// ReferenceEquals returns true if both objects
// point to the same location in memory.
if (String.ReferenceEquals(a, b))
    Console.WriteLine("a and b are interned.");
else
    Console.WriteLine("a and b are not interned.");

// Use String.Copy method to avoid interning.
string c = String.Copy(a);

if (String.ReferenceEquals(a, c))
    Console.WriteLine("a and c are interned.");
else
    Console.WriteLine("a and c are not interned.");

Nell'esempio seguente viene mostrato come confrontare stringhe nel modo preferito tramite i metodi System.String che accettano un'enumerazione StringComparison. Notare che i metodi di istanza String.CompareTo non vengono utilizzati qui, perché nessuno degli overload accetta StringComparison.

// "They dance in the street."
// Linguistically (in Windows), "ss" is equal to 
// the German essetz: 'ß' character in both en-US and de-DE cultures.
string first = "Sie tanzen in die Straße."; 
string second = "Sie tanzen in die Strasse.";

Console.WriteLine("First sentence is {0}", first);
Console.WriteLine("Second sentence is {0}", second);

// Store CultureInfo for the current culture. Note that the original culture
// can be set and retrieved on the current thread object.
System.Threading.Thread thread = System.Threading.Thread.CurrentThread;
System.Globalization.CultureInfo originalCulture = thread.CurrentCulture;

// Set the culture to en-US.
thread.CurrentCulture = new System.Globalization.CultureInfo("en-US");

// For culture-sensitive comparisons, use the String.Compare 
// overload that takes a StringComparison value.
int i = String.Compare(first, second, StringComparison.CurrentCulture);
Console.WriteLine("Comparing in {0} returns {1}.", originalCulture.Name, i);

// Change the current culture to Deutch-Deutchland.
thread.CurrentCulture = new System.Globalization.CultureInfo("de-DE");
i = String.Compare(first, second, StringComparison.CurrentCulture);
Console.WriteLine("Comparing in {0} returns {1}.", thread.CurrentCulture.Name, i);

// For culture-sensitive string equality, use either StringCompare as above
// or the String.Equals overload that takes a StringComparison value.
thread.CurrentCulture = originalCulture;
bool b = String.Equals(first, second, StringComparison.CurrentCulture);
Console.WriteLine("The two strings {0} equal.", b == true ? "are" : "are not");

/*
 * Output:
    First sentence is Sie tanzen in die Straße.
    Second sentence is Sie tanzen in die Strasse.
    Comparing in current culture returns 0.
    The two strings are equal.
 */

Nell'esempio seguente viene mostrato come ordinare e cercare stringhe in una matrice in modo dipendente dalle impostazioni cultura tramite i metodi Array statici che accettano un parametro System.StringComparer.

class SortStringArrays
{
    static void Main()
    {

        string[] lines = new string[]
        {
            @"c:\public\textfile.txt",
            @"c:\public\textFile.TXT",
            @"c:\public\Text.txt",
            @"c:\public\testfile2.txt"
        };

        Console.WriteLine("Non-sorted order:");
        foreach (string s in lines)
        {
            Console.WriteLine("   {0}", s);
        }

        Console.WriteLine("\n\rSorted order:");

        // Specify Ordinal to demonstrate the different behavior.
        Array.Sort(lines, StringComparer.Ordinal);

        foreach (string s in lines)
        {
            Console.WriteLine("   {0}", s);
        }


        string searchString = @"c:\public\TEXTFILE.TXT";
        Console.WriteLine("Binary search for {0}", searchString);
        int result = Array.BinarySearch(lines, searchString, StringComparer.OrdinalIgnoreCase);
        ShowWhere<string>(lines, result);

        //Console.WriteLine("{0} {1}", result > 0 ? "Found" : "Did not find", searchString);

        // Keep the console window open in debug mode.
        System.Console.WriteLine("Press any key to exit.");
        System.Console.ReadKey();
    }

    // Displays where the string was found, or, if not found,
    // where it would have been located.
    private static void ShowWhere<T>(T[] array, int index)
    {
        if (index < 0)
        {
            // If the index is negative, it represents the bitwise
            // complement of the next larger element in the array.
            index = ~index;

            Console.Write("Not found. Sorts between: ");

            if (index == 0)
                Console.Write("beginning of array and ");
            else
                Console.Write("{0} and ", array[index - 1]);

            if (index == array.Length)
                Console.WriteLine("end of array.");
            else
                Console.WriteLine("{0}.", array[index]);
        }
        else
        {
            Console.WriteLine("Found at index {0}.", index);
        }
    }


}
/*
 * Output:
    Non-sorted order:
       c:\public\textfile.txt
       c:\public\textFile.TXT
       c:\public\Text.txt
       c:\public\testfile2.txt

    Sorted order:
       c:\public\Text.txt
       c:\public\testfile2.txt
       c:\public\textFile.TXT
       c:\public\textfile.txt
    Binary search for c:\public\TEXTFILE.TXT
    Found at index 2.
 */

Le classi di insiemi quali System.Collections.Hashtable, System.Collections.Generic.Dictionary<TKey, TValue> e System.Collections.Generic.List<T> dispongono di costruttori che accettano un parametro System.StringComparer quando il tipo degli elementi o delle chiavi è string. In generale, è consigliabile utilizzare questi costruttori quando possibile e specificare Ordinal o OrdinalIgnoreCase.

Vedere anche

Concetti

Confronto di stringhe

Riferimenti

Stringhe (Guida per programmatori C#)

System.Globalization.CultureInfo

System.StringComparer

Altre risorse

Globalizzazione e localizzazione di applicazioni

Cronologia delle modifiche

Data

Cronologia

Motivo

Luglio 2008

Aggiunto argomento.

Correzione di errori nel contenuto.