Gewusst wie: Vergleichen von Zeichenfolgen (C#-Programmierhandbuch)

Wenn Sie Zeichenfolgen vergleichen, erzeugen Sie ein Ergebnis, das besagt, dass eine Zeichenfolge größer oder kleiner als eine andere ist oder dass die beiden Zeichenfolgen gleich sind. Die Regeln, nach denen das Ergebnis bestimmt wird, unterscheiden sich abhängig davon, ob Sie einen Ordinalvergleich oder einen kulturabhängigen Vergleich durchführen. Es ist wichtig, die richtige Art von Vergleich für eine bestimmte Aufgabe zu verwenden.

Verwenden Sie grundlegende Ordinalvergleiche, wenn Sie die Werte zweier Zeichenfolgen vergleichen oder sortieren, ohne linguistische Konventionen zu berücksichtigen. Ein grundlegender ordinaler Vergleich (System.StringComparison.Ordinal) unterscheidet zwischen Groß- und Kleinschreibung, was bedeutet, dass die beiden Zeichenfolgen Zeichen für Zeichen übereinstimmen müssen: „and“ ist nicht gleich „And“ oder „AND“. Eine häufig verwendete Variante ist System.StringComparison.OrdinalIgnoreCase, bei der „and“, „And“ und „AND“ nicht unterschieden werden. StringComparison.OrdinalIgnoreCase wird häufig verwendet, um Dateinamen, Pfadnamen, Netzwerkpfade und jede andere Zeichenfolge, deren Wert basierend auf dem Gebietsschema des Computers des Benutzers nicht geändert wird, zu vergleichen. Weitere Informationen finden Sie unter System.StringComparison.

Kulturabhängige Vergleiche werden normalerweise verwendet, um Zeichenfolgen zu vergleichen und zu sortieren, die von Endbenutzern eingegeben werden, da die Zeichen und Sortierungskonventionen dieser Zeichenfolgen je nach Gebietsschema des Computers des Benutzers variieren können. Sogar Zeichenfolgen, die identische Zeichen enthalten, sortieren je nach Kultur des aktuellen Threads möglicherweise unterschiedlich.

Hinweis

Wenn Sie Zeichenfolgen vergleichen, sollten Sie die Methoden verwenden, die explizit angeben, welche Art von Vergleich Sie durchführen möchten. Dadurch kann der Code viel besser verwaltet und gelesen werden. Verwenden Sie wenn möglich die Überladungen der Methoden der Klassen System.String und System.Array, die den StringComparison-Enumerationsparameter übernehmen, sodass Sie angeben können, welcher Vergleichstyp ausgeführt werden soll. Es empfiehlt sich, beim Vergleichen von Zeichenfolgen die Operatoren == und != zu vermeiden. Vermeiden Sie es außerdem, die String.CompareTo-Instanzmethoden zu verwenden, da keine der Überladungen eine StringComparison übernimmt.

Beispiel

Im folgenden Beispiel wird veranschaulicht, wie Zeichenfolgen, deren Werte sich basierend auf dem Gebietsschema des Computers des Benutzers nicht ändern, ordnungsgemäß verglichen werden. Darüber hinaus wird die Funktion von C# zur Internalisierung von Zeichenfolgen gezeigt. Wenn ein Programm zwei oder mehr identische Zeichenfolgenvariablen deklariert, speichert der Compiler alle am selben Speicherort. Durch Aufrufen der ReferenceEquals-Methode können Sie sehen, dass die beiden Zeichenfolgen tatsächlich auf das gleiche Objekt im Arbeitsspeicher verweisen. Verwenden Sie die String.Copy-Methode, um die Internalisierung zu vermeiden, wie im Beispiel gezeigt.


// 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.");

// Output:
// Ordinal comparison: C:\users and C:\Users are not equal.
// Ordinal ignore case: C:\users and C:\Users are equal.
// a and b are interned.
// a and c are not interned.

Beispiel

Das folgende Beispiel zeigt, wie Zeichenfolgen bevorzugt verglichen werden, indem die System.String-Methoden verwendet werden, die eine StringComparison-Enumeration übernehmen. Beachten Sie, dass die String.CompareTo-Instanzmethoden hier nicht verwendet werden, da keine der Überladungen eine StringComparison übernimmt.

// "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 en-US returns 0.
    Comparing in de-DE returns 0.
    The two strings are equal.
 */

Beispiel

Das folgende Beispiel zeigt, wie Sie Zeichenfolgen in einem Array auf kulturabhängige Weise mithilfe der statischen Array-Methoden, die einen System.StringComparer-Parameter akzeptieren, sortieren und danach suchen.

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

Auflistungsklassen wie System.Collections.Hashtable, System.Collections.Generic.Dictionary<TKey,TValue> und System.Collections.Generic.List<T> verfügen über Konstruktoren, die einen System.StringComparer-Parameter übernehmen, wenn der Typ des Elements oder der Schlüssel string ist. Im Allgemeinen sollten Sie nach Möglichkeit diese Konstruktoren verwenden und entweder Ordinal oder OrdinalIgnoreCase angeben.

Siehe auch

System.Globalization.CultureInfo
System.StringComparer
Zeichenfolgen
Vergleichen von Zeichenfolgen
Globalisieren und Lokalisieren von Anwendungen