Diferencia entre InvariantCulture y Ordinal string comparison


Al comparar dos cadenas en c# para la igualdad, ¿cuál es la diferencia entre la cultura invariante y la comparación ordinal?

Author: Adrian Godong, 2009-01-29

9 answers

InvariantCulture

Utiliza un conjunto "estándar" de ordenamientos de caracteres (a, b, c,... sucesivamente.). Esto contrasta con algunos lugares específicos, que pueden ordenar caracteres en diferentes órdenes ('a-con-agudo' puede ser anterior o después de 'a', dependiendo de la configuración regional, y así sucesivamente).

Ordinal

Por otro lado, mira puramente los valores de los bytes crudos que representan el carácter.


Hay una gran muestra en http://msdn.microsoft.com/en-us/library/e6883c06.aspx que muestra los resultados de los diversos valores de StringComparison. Todo el camino al final, se muestra (extracto):

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)

Se puede ver que donde InvariantCulture rendimientos (U+0069, U+0049, U+00131), Ordinal rendimientos (U+0049, U+0069, U+00131).

 259
Author: JaredReisinger,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-08-15 09:54:42

Sí importa, por ejemplo - hay una cosa llamada expansión de caracteres

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

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

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

Con InvariantCulture el carácter ß se expande a ss.

 176
Author: Bond,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-08-31 18:58:03

Apuntando a Las mejores prácticas para Usar Cadenas en. NET Framework :

  • Use StringComparison.Ordinal o StringComparison.OrdinalIgnoreCase para comparaciones como su valor predeterminado seguro para la coincidencia de cadenas agnósticas de cultura.
  • Utilice comparaciones con StringComparison.Ordinal o StringComparison.OrdinalIgnoreCase para un mejor rendimiento.
  • Utilice los valores no lingüísticos StringComparison.Ordinal o StringComparison.OrdinalIgnoreCase en lugar de las operaciones de cadena basadas en CultureInfo.InvariantCulture cuando la comparación sea lingüísticamente irrelevante (simbólica, por ejemplo).

Y por último:

  • No utilice operaciones de cadena basadas en StringComparison.InvariantCulture en la mayoría de los casos. Una de las pocas excepciones es cuando se persisten datos lingüísticamente significativos pero culturalmente agnósticos.
 73
Author: Dariusz,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-12-12 10:10:38

Otra diferencia útil (en inglés donde los acentos son poco comunes) es que una comparación de InvariantCulture compara las cadenas enteras por mayúsculas y minúsculas primero, y luego, si es necesario (y solicitado) distingue por mayúsculas y minúsculas después de comparar primero solo en las letras distintas. (Por supuesto, también puede hacer una comparación sin distinción de mayúsculas y minúsculas, que no distinguirá por mayúsculas y minúsculas.) Corregido: Las letras acentuadas se consideran otro sabor de las mismas letras y se compara la cadena primero ignorando acentos y luego considerándolos si todas las letras generales coinciden (al igual que con mayúsculas y minúsculas diferentes, excepto que no se ignoran en última instancia en una comparación insensible a mayúsculas y minúsculas). Esto agrupa versiones acentuadas de la misma palabra cerca una de la otra en lugar de separarlas completamente en la primera diferencia de acento. Este es el orden de clasificación que normalmente se encuentra en un diccionario, con palabras en mayúscula que aparecen justo al lado de sus equivalentes en minúsculas, y letras acentuadas que están cerca de la carta no certificada correspondiente.

Una comparación ordinal compara estrictamente los valores de los caracteres numéricos, deteniéndose en la primera diferencia. Esto ordena las letras en mayúsculas completamente separadas de las letras minúsculas (y las letras acentuadas presumiblemente separadas de esas), por lo que las palabras en mayúsculas no se clasificarían ni cerca de sus equivalentes en minúsculas.

InvariantCulture también considera que las mayúsculas son mayores que las minúsculas, mientras que Ordinal considera que las mayúsculas son menores que minúsculas (un remanente de ASCII de los viejos tiempos antes de que las computadoras tuvieran letras minúsculas, las letras mayúsculas se asignaban primero y por lo tanto tenían valores más bajos que las letras minúsculas agregadas más tarde).

Por ejemplo, por Ordinal: "0" < "9" < "A" < "Ab" < "Z" < "a" < "aB" < "ab" < "z" < "Á" < "Áb" < "á" < "áb"

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

 54
Author: Rob Parker,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-08-28 11:27:56

Invariante es un tipo lingüísticamente apropiado de comparación.
Ordinal es un tipo binario de comparación. (más rápido)
Véase http://www.siao2.com/2004/12/29/344136.aspx

 26
Author: DanH,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-10-08 01:03:58

Aunque la pregunta es sobre igualdad, para una referencia visual rápida, aquí el orden de algunas cadenas ordenadas usando un par de culturas que ilustran algunas de las idiosincrasias que existen.

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 ß ァ ぁ ア あ 亜

Observaciones:

  • de-DE, ja-JP, y en-US ordenar de la misma manera
  • Invariant solo clasifica ss y ß de manera diferente a las tres culturas anteriores
  • da-DK ordena de manera bastante diferente
  • la bandera IgnoreCase importa para todos los muestreados culturas

El código utilizado para generar la tabla anterior:

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));
}
 26
Author: Eugene Beresovsky,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-11-03 23:45:38

Aquí hay un ejemplo donde la comparación de igualdad de cadenas usando InvariantCultureIgnoreCase y OrdinalIgnoreCase no dará los mismos resultados:

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 ejecuta esto, equals1 será false, y equals2 será true.

 3
Author: Dwedit,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-07-11 21:22:57

No es necesario usar ejemplos de caracteres unicode para mostrar la diferencia. Aquí hay un ejemplo simple que descubrí hoy que es sorprendente, que consiste solo en caracteres ASCII.

De acuerdo con la tabla ASCII, 0 (0x48) es menor que _ (0x95) cuando se compara ordinariamente. InvariantCulture diría lo contrario (código de PowerShell a continuación):

PS> [System.StringComparer]::Ordinal.Compare("_", "0")
47
PS> [System.StringComparer]::InvariantCulture.Compare("_", "0")
-1
 1
Author: KFL,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-11-29 20:09:08

Siempre intente usar InvariantCulture en aquellos métodos de cadena que lo aceptan como sobrecarga. Al usar InvariantCulture estás en un lado seguro. Muchos programadores de. NET pueden no usar esta funcionalidad, pero si su software será utilizado por diferentes culturas, InvariantCulture es una característica extremadamente útil.

 -6
Author: George,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-02-18 14:52:55