Al comparar dos cadenas en c # para la igualdad, ¿cuál es la diferencia entre InvariantCulture y la comparación ordinal?
c#
.net
string-comparison
ordinal
Kapil
fuente
fuente
String1.Equals(String2, StringComparison.Ordinal)
, es mejor usar elString1 == String2
que es intrínsecamenteString1.Equals(String2)
y es, por defecto, una comparación entre mayúsculas y minúsculas ordinales.==
"mejor", pero es a) más corto, b) menos explícito sobre lo que hace exactamente yc)String1
puede ser nulo sin la comparación arrojando aNullReferenceException
.StringComparison
tipo. En el caso de la comparación de cadenas, significaString.Equals
.NullReferenceException
puede simplemente usar el método estático:String.Equals(string1, string2, StringComparison.Ordinal)
.Respuestas:
Cultura Invariante
Utiliza un conjunto "estándar" de ordenamiento de caracteres (a, b, c, ... etc.). Esto contrasta con algunas configuraciones regionales específicas, que pueden ordenar los caracteres en diferentes órdenes ('a-with-acute' puede estar antes o después de 'a', dependiendo de la configuración regional, y así sucesivamente).
Ordinal
Por otro lado, analiza únicamente los valores de los bytes sin procesar 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 distintos valores de StringComparison. Todo el camino al final, muestra (extracto):
Puede ver que donde InvariantCulture rinde (U + 0069, U + 0049, U + 00131), Ordinal rinde (U + 0049, U + 0069, U + 00131).
fuente
Sí importa, por ejemplo: hay una cosa llamada expansión de personaje
Con
InvariantCulture
el carácter ß se expande a ss.fuente
Ordinal
yInvariantCulture
? De eso se trata la pregunta original.ß
, debe tenerse en cuenta queß
al menos en alemán equivale a un doble s, Fuente: en.wikipedia.org/wiki/%C3%9Fß
ess
intercambiablemente en alemán (soy un hablante nativo). Hay casos en que ambos son legales (pero a menudo uno está desactualizado / no recomendado) y hay casos en los que solo se permite un formulario.Señalando las mejores prácticas para usar cadenas en .NET Framework :
StringComparison.Ordinal
oStringComparison.OrdinalIgnoreCase
para comparaciones como su valor predeterminado seguro para la coincidencia de cadenas independiente de la cultura.StringComparison.Ordinal
oStringComparison.OrdinalIgnoreCase
para un mejor rendimiento.StringComparison.Ordinal
o enStringComparison.OrdinalIgnoreCase
lugar de las operaciones de cadena en función deCultureInfo.InvariantCulture
cuándo la comparación es lingüísticamente irrelevante (simbólica, por ejemplo).Y finalmente:
StringComparison.InvariantCulture
en la mayoría de los casos . Una de las pocas excepciones es cuando persiste datos lingüísticamente significativos pero culturalmente agnósticos.fuente
Otra diferencia útil (en inglés, donde los acentos son poco comunes) es que una comparación de InvariantCulture compara las cadenas completas por mayúsculas y minúsculas primero, y luego si es necesario (y solicitado) distingue por mayúsculas y minúsculas después de primero comparar solo las letras distintas. (También puede hacer una comparación entre mayúsculas y minúsculas, por supuesto, que no distinguirá entre mayúsculas y minúsculas). Corregido:Las letras acentuadas se consideran otro sabor de las mismas letras y la cadena se compara primero ignorando los acentos y luego contabilizándolos si todas las letras generales coinciden (al igual que con mayúsculas y minúsculas, excepto que finalmente no se ignoran en una comparación que no distingue entre mayúsculas y minúsculas). Esto agrupa versiones acentuadas de la misma palabra, por lo demás, cercanas entre sí en lugar de estar completamente separadas en la primera diferencia de acento. Este es el orden de clasificación que normalmente encontraría en un diccionario, con palabras en mayúscula que aparecen justo al lado de sus equivalentes en minúsculas, y las letras acentuadas están cerca de la letra sin acento correspondiente.
Una comparación ordinal se compara estrictamente con los valores de caracteres numéricos, deteniéndose en la primera diferencia. Esto clasifica las letras en mayúscula completamente separadas de las letras minúsculas (y las letras acentuadas presumiblemente separadas de esas), por lo que las palabras en mayúscula no se clasificarían cerca de sus equivalentes en minúsculas.
InvariantCulture también considera que las mayúsculas son más grandes que las minúsculas, mientras que Ordinal considera que las mayúsculas son menos 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 asignaron primero y por lo tanto tenían valores más bajos que las minúsculas añadido 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"
fuente
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 existentes.
Observaciones:
de-DE
,ja-JP
yen-US
ordenar de la misma maneraInvariant
solo clasificass
y de maneraß
diferente a las tres culturas anterioresda-DK
se clasifica de manera bastante diferenteIgnoreCase
bandera es importante para todas las culturas muestreadasEl código utilizado para generar la tabla anterior:
fuente
CultureComparer
que podamos usar para verificar. Para esta tabla, laDanish
cultura (información) resultó ser muy importante.)Invariante es un tipo de comparación lingüísticamente apropiado.
El ordinal es un tipo binario de comparación. (más rápido)
Ver http://www.siao2.com/2004/12/29/344136.aspx
fuente
Aquí hay un ejemplo donde la comparación de igualdad de cadenas usando InvariantCultureIgnoreCase y OrdinalIgnoreCase no dará los mismos resultados:
Si ejecuta esto, equals1 será falso y equals2 será verdadero.
fuente
a="\x00e9"
(e agudo) yb="\x0065\x0301"
(e combinado con un acento agudo),StringComparer.Ordinal.Equals(a, b)
devolverá falso mientrasStringComparer.InvariantCulture.Equals(a, b)
que devolverá verdadero.No es necesario usar extractos 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) en comparación ordinalmente. InvariantCulture diría lo contrario (código de PowerShell a continuación):fuente
Siempre trate de usar InvariantCulture en esos métodos de cadena que lo aceptan como sobrecarga. Al usar InvariantCulture estás en un lado seguro. Muchos programadores .NET pueden no usar esta funcionalidad, pero si su software será utilizado por diferentes culturas, InvariantCulture es una característica extremadamente útil.
fuente