Partager via


Comment : comparer des chaînes (Guide de programmation C#)

Mise à jour : Juillet 2008

Lorsque vous comparez des chaînes, vous obtenez un résultat indiquant qu'une chaîne est supérieure ou inférieure à l'autre, ou que les deux chaînes sont égales. Les règles qui déterminent le résultat sont différentes selon que vous effectuez une comparaison ordinale ou une comparaison dépendante de la culture. Il est important d'utiliser le type correct de comparaison pour la tâche spécifique.

Utilisez la comparaison ordinale de base lorsque vous devez comparer ou trier les valeurs de deux chaînes sans tenir compte de conventions linguistiques. Les comparaisons ordinales de base (Ordinal) respectent la casse, ce qui signifie que les caractères des deux chaînes doivent correspondre : « et » n'est pas l'équivalent de « Et » ni de « ET ». Une variante utilisée fréquemment est OrdinalIgnoreCase, qui trouve « et », « Et » et « ET ». StringComparison.OrdinalIgnoreCase est souvent utilisé pour comparer les noms de fichiers, les noms de chemins d'accès, les chemins d'accès réseau et toute autre chaîne dont la valeur ne change pas en fonction des paramètres régionaux de l'ordinateur de l'utilisateur.

Les comparaisons dépendantes de la culture sont utilisées en général pour comparer et trier des chaînes entrées par les utilisateurs finals parce que les caractères et les conventions de tri de ces chaînes peuvent varier en fonction des paramètres régionaux de l'ordinateur de l'utilisateur. Même les chaînes qui contiennent des caractères identiques peuvent être triées différemment selon la culture du thread actuel.

Remarque :

Lorsque vous comparez des chaînes, vous devez utiliser les méthodes qui spécifient explicitement le type de comparaison que vous projetez d'effectuer. Cela rend votre code beaucoup plus facile à gérer et à lire. Dans la mesure du possible, utilisez les surcharges des méthodes des classes System.String et System.Array, qui acceptent les paramètres d'énumération StringComparison, afin que vous puissiez spécifier le type de comparaison à effectuer. Il vaut mieux éviter d'utiliser les opérateurs == et != lorsque vous comparez des chaînes. Évitez également d'utiliser les méthodes d'instance String.CompareTo parce qu'aucune des surcharges n'accepte de StringComparison.

Exemple

L'exemple suivant indique comment comparer correctement des chaînes dont les valeurs ne changent pas en fonction des paramètres régionaux de l'ordinateur de l'utilisateur. De plus, il montre également la fonctionnalité d'internement de chaîne de C#. Lorsqu'un programme déclare plusieurs variables chaîne identiques, le compilateur les stocke toutes au même emplacement. En appelant la méthode ReferenceEquals, vous constatez que les deux chaînes font en fait référence au même objet en mémoire. Utilisez la méthode String.Copy pour éviter l'internement, comme illustré dans l'exemple.

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

L'exemple suivant indique comment comparer des chaînes de la façon voulue en utilisant les méthodes System.String, qui acceptent les énumérations StringComparison. Notez que les méthodes d'instance String.CompareTo ne sont pas utilisées ici, parce qu'aucune des surcharges n'accepte de 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.
 */

L'exemple suivant indique comment trier et rechercher des chaînes dans un tableau d'une manière dépendante de la culture, en utilisant les méthodes Array statiques, qui acceptent les paramètres 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.
 */

Les classes de collection telles que System.Collections.Hashtable, System.Collections.Generic.Dictionary<TKey, TValue> et System.Collections.Generic.List<T> ont des constructeurs qui acceptent les paramètres System.StringComparer lorsque le type des éléments ou des clés est string. En général, vous devez utiliser ces constructeurs dès que cela est possible et spécifier Ordinal ou OrdinalIgnoreCase.

Voir aussi

Concepts

Comparaison de chaînes

Référence

Chaînes (Guide de programmation C#)

System.Globalization.CultureInfo

System.StringComparer

Autres ressources

Globalisation et localisation d'applications

Historique des modifications

Date

Historique

Raison

Juillet 2008

Rubrique ajoutée

Résolution des bogues de contenu.