Question Différence entre InvariantCulture et Ordinal


Lorsque vous comparez deux chaînes dans c # pour l'égalité, quelle est la différence entre InvariantCulture et la comparaison ordinale?


435
2018-01-29 18:21


origine


Réponses:


InvariantCulture

Utilise un ensemble "standard" d'ordonnances de caractères (a, b, c, ... etc.). Ceci est en contraste avec certains paramètres régionaux spécifiques, qui peuvent trier les caractères dans différents ordres ('a-with-acute' peut être avant ou après 'a', selon les paramètres régionaux, etc.).

Ordinal

D'un autre côté, regarde uniquement les valeurs du (des) octet (s) brut (s) qui représentent le personnage.


Il y a un bon échantillon à http://msdn.microsoft.com/en-us/library/e6883c06.aspx qui montre les résultats des différentes valeurs de StringComparison. Tout le chemin à la fin, ça se voit:

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 là où les rendements d'InvariantCulture (U + 0069, U + 0049, U + 00131), les rendements ordinaux (U + 0049, U + 0069, U + 00131).


256
2018-01-29 18:44



Cela a de l'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 caractère ß est élargi à ss.


169
2017-11-20 00:40



Pointant vers Meilleures pratiques pour l'utilisation de chaînes dans le .NET Framework:

  • Utilisation StringComparison.Ordinal ou StringComparison.OrdinalIgnoreCase pour les comparaisons en tant que votre valeur par défaut sûre pour la correspondance de chaînes non agnostique.
  • Utiliser des comparaisons avec StringComparison.Ordinal ou StringComparison.OrdinalIgnoreCase pour de meilleures performances.
  • Utilisez le non-linguistique StringComparison.Ordinal ou StringComparison.OrdinalIgnoreCase valeurs au lieu d'opérations de chaîne basées sur CultureInfo.InvariantCulture lorsque la comparaison est linguistiquement non pertinente (symbolique, par exemple).

Et enfin:

  • N'utilisez pas d'opérations de chaîne basées sur StringComparison.InvariantCulture dans la plupart des cas. L'une des rares exceptions est lorsque vous persistez à avoir des données significatives sur le plan linguistique mais culturellement agnostiques.

68
2018-02-25 10:48



Une autre différence pratique (en anglais où les accents sont rares) est qu'une comparaison InvariantCulture compare les chaînes entières en commençant par insensible à la casse, et si nécessaire (et demandée), distingue par cas après avoir d'abord comparé les lettres distinctes. (Vous pouvez également faire une comparaison insensible à la casse, bien sûr, qui ne distinguera pas par cas.) Corrigée: Les lettres accentuées sont considérées comme une autre saveur des mêmes lettres et la chaîne est comparée d'abord en ignorant les accents, puis en les comptabilisant si les lettres générales correspondent (tout comme dans un cas différent, sauf finalement ignoré dans une comparaison insensible à la casse). Ceci groupe les versions accentuées du même mot près l'une de l'autre au lieu de se séparer complètement à la première différence d'accent. C'est l'ordre de tri que vous trouverez généralement dans un dictionnaire, avec les mots en majuscules apparaissant juste à côté de leurs équivalents en minuscules, et les lettres accentuées étant près de la lettre non accentuée correspondante.

Une comparaison ordinale se compare strictement aux valeurs des caractères numériques, s'arrêtant à la première différence. Ceci trie les lettres majuscules complètement séparées des lettres minuscules (et les lettres accentuées sont probablement séparées de celles-ci), de sorte que les mots en majuscules ne se rangent nulle part près de leurs équivalents minuscules.

InvariantCulture considère également que les majuscules sont supérieures aux minuscules, alors qu'Ordinal considère les majuscules comme minuscules (une rémanence de l'ASCII des anciens jours avant que les ordinateurs aient des lettres minuscules, les lettres majuscules étaient attribuées en premier et avaient donc des valeurs inférieures aux lettres minuscules) ajouté 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 "


54
2018-02-09 19:06



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


25
2018-06-02 20:56



Bien que la question concerne égalité, pour une référence visuelle rapide, voici l'ordre de certaines chaînes trié en utilisant quelques cultures illustrant certaines des particularités 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 trier de la même manière
  • Invariant seulement des sortes ss et ß différemment des trois cultures ci-dessus
  • da-DK trie différemment
  • la IgnoreCase drapeau importe pour toutes les cultures échantillonnées

Le 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));
}

22
2018-06-10 23:39



Voici un exemple où la comparaison d'égalité de chaînes utilisant InvariantCultureIgnoreCase et 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 lancez ceci, equals1 sera faux et equals2 sera vrai.


3
2017-07-11 21:22



Pas besoin d'utiliser des exemples de char unicode pour montrer la différence. Voici un exemple simple que j'ai trouvé aujourd'hui qui est surprenant, composé uniquement de caractères ASCII.

Selon la table ASCII, 0 (0x48) est plus petit que _ (0x95) comparé normalement. InvariantCulture dirait le contraire (code PowerShell ci-dessous):

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

1
2017-11-29 20:09



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 peuvent ne pas utiliser cette fonctionnalité, mais si votre logiciel est utilisé par différentes cultures, InvariantCulture est une fonctionnalité extrêmement pratique.


-6
2018-02-18 14:52