Question

Lors de la comparaison de deux chaînes de c # pour l'égalité, quelle est la différence entre la comparaison InvariantCulture et Ordinal?

Était-ce utile?

La solution

InvariantCulture

Utilise un " standard " ensemble d'ordonnancement des caractères (a, b, c, ... etc.). Cela contraste avec certains paramètres régionaux spécifiques, qui peuvent trier les caractères dans des ordres différents ("a-with-aiguë" peut être avant ou après "a", en fonction de la et ainsi de suite).

Ordinal

D'autre part, regarde uniquement les valeurs du ou des octets bruts représentant le caractère.

Il existe un excellent échantillon à l'adresse http://msdn.microsoft.com/en. -us / library / e6883c06.aspx qui affiche les résultats des différentes valeurs de StringComparison. Tout au long à la fin, cela montre (extrait):

StringComparison.InvariantCulture:
LATIN SMALL LETTER I (U+0069) is less than LATIN SMALL LETTER DOTLESS I (U+0131)
LATIN SMALL LETTER I (U+0069) is less than LATIN CAPITAL LETTER I (U+0049)
LATIN SMALL LETTER DOTLESS I (U+0131) is greater than LATIN CAPITAL LETTER I (U+0049)

StringComparison.Ordinal:
LATIN SMALL LETTER I (U+0069) is less than LATIN SMALL LETTER DOTLESS I (U+0131)
LATIN SMALL LETTER I (U+0069) is greater than LATIN CAPITAL LETTER I (U+0049)
LATIN SMALL LETTER DOTLESS I (U+0131) is greater than LATIN CAPITAL LETTER I (U+0049)

Vous pouvez voir que les rendements d'InvariantCulture (U + 0069, U + 0049, U + 00131), les rendements ordinaux (U + 0049, U + 0069, U + 00131).

Autres conseils

Cela a son importance, par exemple - il y a une chose appelée expansion de caractère

var s1 = "Strasse";
var s2 = "Straße";

s1.Equals(s2, StringComparison.Ordinal);           //false
s1.Equals(s2, StringComparison.InvariantCulture);  //true

Avec InvariantCulture le & # 223; le caractère est étendu à ss.

Pointant vers les Meilleures pratiques d'utilisation des chaînes dans le .NET Framework :

  • Utilisez StringComparison.Ordinal ou StringComparison.OrdinalIgnoreCase pour les comparaisons comme valeur de sécurité par défaut pour la correspondance de chaînes dépendant de la culture.
  • Utilisez les comparaisons avec CultureInfo.InvariantCulture ou StringComparison.InvariantCulture pour améliorer les performances.
  • Utilisez les valeurs non-linguistiques <=> ou <=> au lieu d'opérations sur des chaînes basées sur <=> lorsque la comparaison n'a pas d'importance linguistique (symbolique, par exemple).

Et enfin:

  • N'utilisez pas d'opérations sur les chaînes basées sur <=> dans la plupart des cas . Une des rares exceptions concerne les données persistantes sur le plan linguistique mais culturellement indépendantes.

Une autre différence pratique (en anglais, où les accents sont rares) est qu'une comparaison InvariantCulture compare les chaînes entières en respectant les majuscules, et ensuite, si nécessaire (et en le sollicitant), distingue cas par cas après avoir comparé uniquement les lettres distinctes. (Vous pouvez également faire une comparaison insensible à la casse, bien sûr, sans distinction de casse.) Corrigé: Les lettres accentuées sont considérées comme une autre version des mêmes lettres et la chaîne est comparée en premier. ignorer les accents et les comptabiliser ensuite si les lettres générales correspondent toutes (de la même manière que pour des cas différents, sauf que finalement, elles ne sont pas ignorées dans une comparaison ne respectant pas la casse). Cela regroupe les versions accentuées du même mot proches les unes des autres au lieu d'être complètement séparées à la première différence d'accent. C’est dans cet ordre de tri que vous trouverez généralement dans un dictionnaire: les mots en majuscules apparaissent juste à côté de leurs équivalents minuscules et les lettres accentuées à proximité de la lettre non accentuée correspondante.

Une comparaison ordinale compare strictement les valeurs des caractères numériques, en s’arrêtant à la première différence. Ceci trie les lettres majuscules complètement séparées des minuscules (et les lettres accentuées vraisemblablement distinctes de celles-ci), ainsi les mots en majuscule ne tiendraient nulle part près de leurs équivalents minuscules.

InvariantCulture considère également que les majuscules sont plus grandes que les minuscules, alors qu’Ordinal considère que les majuscules sont moins que minuscules (une réserve d’ASCII d’avant que les ordinateurs aient des minuscules, les majuscules ont été attribuées en premier et avaient donc des valeurs inférieures à les lettres minuscules ajoutées plus tard).

Par exemple, par Ordinal: "0" < "9" < "A" < "Ab" < "Z" < "a" < "aB" < "ab" < "z" < "Á" < "Áb" < "á" < "áb"

Et par InvariantCulture: "0" < "9" < "a" < "A" < "á" < "Á" < "ab" < "aB" < "Ab" < "áb" < "Áb" < "z" < "Z"

Bien que la question porte sur l'égalité , pour une référence visuelle rapide, voici l'ordre de certaines chaînes triées à l'aide de quelques cultures illustrant certaines des idiosyncrasies existantes.

Ordinal          0 9 A Ab a aB aa ab ss Ä Äb ß ä äb ぁ あ ァ ア 亜 A
IgnoreCase       0 9 a A aa ab Ab aB ss ä Ä äb Äb ß ぁ あ ァ ア 亜 A
--------------------------------------------------------------------
InvariantCulture 0 9 a A A ä Ä aa ab aB Ab äb Äb ss ß ァ ぁ ア あ 亜
IgnoreCase       0 9 A a A Ä ä aa Ab aB ab Äb äb ß ss ァ ぁ ア あ 亜
--------------------------------------------------------------------
da-DK            0 9 a A A ab aB Ab ss ß ä Ä äb Äb aa ァ ぁ ア あ 亜
IgnoreCase       0 9 A a A Ab aB ab ß ss Ä ä Äb äb aa ァ ぁ ア あ 亜
--------------------------------------------------------------------
de-DE            0 9 a A A ä Ä aa ab aB Ab äb Äb ß ss ァ ぁ ア あ 亜
IgnoreCase       0 9 A a A Ä ä aa Ab aB ab Äb äb ss ß ァ ぁ ア あ 亜
--------------------------------------------------------------------
en-US            0 9 a A A ä Ä aa ab aB Ab äb Äb ß ss ァ ぁ ア あ 亜
IgnoreCase       0 9 A a A Ä ä aa Ab aB ab Äb äb ss ß ァ ぁ ア あ 亜
--------------------------------------------------------------------
ja-JP            0 9 a A A ä Ä aa ab aB Ab äb Äb ß ss ァ ぁ ア あ 亜
IgnoreCase       0 9 A a A Ä ä aa Ab aB ab Äb äb ss ß ァ ぁ ア あ 亜

Observations:

  • de-DE, ja-JP et en-US trient de la même manière
  • Invariant ne trie que ss et ß différemment des trois cultures ci-dessus
  • da-DK effectue un tri assez différent
  • le IgnoreCase drapeau est important pour toutes les cultures de l'échantillon

Code utilisé pour générer le tableau ci-dessus:

var l = new List<string>
    { "0", "9", "A", "Ab", "a", "aB", "aa", "ab", "ss", "ß",
      "Ä", "Äb", "ä", "äb", "あ", "ぁ", "ア", "ァ", "A", "亜" };

foreach (var comparer in new[]
{
    StringComparer.Ordinal,
    StringComparer.OrdinalIgnoreCase,
    StringComparer.InvariantCulture,
    StringComparer.InvariantCultureIgnoreCase,
    StringComparer.Create(new CultureInfo("da-DK"), false),
    StringComparer.Create(new CultureInfo("da-DK"), true),
    StringComparer.Create(new CultureInfo("de-DE"), false),
    StringComparer.Create(new CultureInfo("de-DE"), true),
    StringComparer.Create(new CultureInfo("en-US"), false),
    StringComparer.Create(new CultureInfo("en-US"), true),
    StringComparer.Create(new CultureInfo("ja-JP"), false),
    StringComparer.Create(new CultureInfo("ja-JP"), true),
})
{
    l.Sort(comparer);
    Console.WriteLine(string.Join(" ", l));
}

L’invariant est un type de comparaison approprié sur le plan linguistique.
Ordinal est un type de comparaison binaire. (plus rapide)
Voir http://www.siao2.com/2004/12/29/344136. aspx

Voici un exemple où la comparaison de l'égalité des chaînes à l'aide d'InvariantCultureIgnoreCase et d'OrdinalIgnoreCase ne donnera pas les mêmes résultats:

string str = "\xC4"; //A with umlaut, Ä
string A = str.Normalize(NormalizationForm.FormC);
//Length is 1, this will contain the single A with umlaut character (Ä)
string B = str.Normalize(NormalizationForm.FormD);
//Length is 2, this will contain an uppercase A followed by an umlaut combining character
bool equals1 = A.Equals(B, StringComparison.OrdinalIgnoreCase);
bool equals2 = A.Equals(B, StringComparison.InvariantCultureIgnoreCase);

Si vous exécutez cette opération, equals1 sera faux et equals2 sera vrai.

Inutile d'utiliser des exemples de caractères unicode sophistiqués pour montrer la différence. Voici un exemple simple que j'ai découvert aujourd'hui et qui est surprenant, composé uniquement de caractères ASCII.

Selon le tableau ASCII, 0 (0x48) est inférieur à _ (0x95) par comparaison. InvariantCulture dirait le contraire (code PowerShell ci-dessous):

PS> [System.StringComparer]::Ordinal.Compare("_", "0")
47
PS> [System.StringComparer]::InvariantCulture.Compare("_", "0")
-1

Essayez toujours d'utiliser InvariantCulture dans les méthodes de chaîne qui l'acceptent en tant que surcharge. En utilisant InvariantCulture, vous êtes en sécurité. De nombreux programmeurs .NET ne peuvent pas utiliser cette fonctionnalité, mais si votre logiciel sera utilisé par différentes cultures, InvariantCulture est une fonctionnalité extrêmement pratique.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top