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

Wenn Sie Zeichenfolgen vergleichen, führt dies zu einem Ergebnis, das besagt, dass eine Zeichenfolge größer oder kleiner ist als die andere oder dass die beiden Zeichenfolgen gleich sind. Die Regeln, nach denen das Ergebnis bestimmt wird, sind unterschiedlich, je nachdem, 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 die grundlegenden ordinalen Vergleiche, wenn Sie die Werte von zwei Zeichenfolgen ohne Berücksichtigung von linguistischen Konventionen vergleichen oder sortieren müssen. Beim grundlegenden ordinalen Vergleich (System.StringComparison.Ordinal) wird die Groß-/Kleinschreibung berücksichtigt. Dies bedeutet, dass die beiden Zeichenfolgen Zeichen für Zeichen übereinstimmen müssen: "und" stimmt nicht mit "Und" oder "UND" überein. Eine häufig verwendete Variante ist System.StringComparison.OrdinalIgnoreCase, bei der "und", "Und" und "UND" übereinstimmen. StringComparison.OrdinalIgnoreCase wird häufig verwendet, um Dateinamen, Pfadnamen, Netzwerkpfade und jede andere Zeichenfolge zu vergleichen, deren Wert sich nicht basierend auf dem Gebietsschema des Computers des Benutzers ändert. Weitere Informationen finden Sie unter System.StringComparison.

Kulturabhängige Vergleiche werden in der Regel verwendet, um Zeichenfolgen zu vergleichen oder zu sortieren, die von den 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, werden je nach Kultur des aktuellen Threads verschieden sortiert.

Tipp

Wenn Sie Zeichenfolgen vergleichen, sollten Sie die Methoden verwenden, mit denen ausdrücklich angegeben wird, welchen Vergleich Sie durchführen möchten. So kann Ihr Code viel besser verwaltet werden und ist besser lesbar. Verwenden Sie die Überladungen der Methoden der System.String-Klasse und der System.Array-Klasse, die einen StringComparison-Enumerationsparameter übernehmen, damit Sie angeben können, welche Art des Vergleichs ausgeführt werden soll. Am besten vermeiden Sie die Verwendung der Operatoren == und !=, wenn Sie Zeichenfolgen vergleichen. Vermeiden Sie auch die Verwendung der String.CompareTo-Instanzenmethoden, da keiner der Überladungen einen StringComparison akzeptiert.

Beispiel

Im folgenden Beispiel wird dargestellt, wie Zeichenfolgen ordnungsgemäß verglichen werden, deren Werte sich nicht basierend auf dem Gebietsschema des Computers des Benutzers ändern. Außerdem wird auch das C#-Feature Internalisierung von Zeichenfolgen erläutert. Wenn ein Programm mehrere identische Zeichenfolgenvariablen deklariert, speichert der Compiler alle am selben Speicherort. Wenn Sie die ReferenceEquals-Methode aufrufen, sehen Sie, dass die beiden Zeichenfolgen auf dasselbe Objekt im Arbeitsspeicher verweisen. Verwenden Sie die String.Copy-Methode, um eine Internalisierung zu vermeiden, wie im folgenden Beispiel dargestellt.


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

Im folgenden Beispiel wird dargestellt, wie Zeichenfolgen auf die bevorzugte Weise mithilfe der System.String-Methoden verglichen werden, die eine StringComparison-Enumeration akzeptieren. Beachten Sie, dass die String.CompareTo-Instanzenmethoden hier nicht verwendet werden, da keine der Überladungen einen StringComparison akzeptiert.

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

Im folgenden Beispiel wird dargestellt, wie Zeichenfolgen sortiert werden und in einem Array auf kulturabhängige Weise danach gesucht wird. Verwenden Sie dazu die statischen Array-Methoden, die einen System.StringComparer-Parameter akzeptieren.

    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 z. B. System.Collections.Hashtable, System.Collections.Generic.Dictionary<TKey, TValue> und System.Collections.Generic.List<T> verfügen über Konstruktoren, die einen System.StringComparer-Parameter akzeptieren, wenn der Typ der Elemente oder Schlüssel string lautet. Im Allgemeinen sollten Sie wann immer möglich diese Konstruktoren verwenden und entweder Ordinal oder OrdinalIgnoreCase angeben.

Siehe auch

Referenz

Zeichenfolgen (C#-Programmierhandbuch)

System.Globalization.CultureInfo

System.StringComparer

Konzepte

Vergleichen von Zeichenfolgen

Weitere Ressourcen

Globalisieren und Lokalisieren von Anwendungen