c# - una - Diferencia entre InvariantCulture y la comparación de cadenas ordinales
string.compare c# (9)
Cultura invariante
Utiliza un conjunto "estándar" de ordenación 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 ser antes o después de ''a'', dependiendo de la configuración regional, etc.).
Ordinal
Por otro lado, observa ú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 diversos valores de StringComparison. Hasta el final, se muestra (extraído):
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 los rendimientos de InvariantCulture (U + 0069, U + 0049, U + 00131), los rendimientos ordinales (U + 0049, U + 0069, U + 00131).
Cuando se comparan dos cadenas en c # para igualdad, ¿cuál es la diferencia entre InvariantCulture y la comparación Ordinal?
Apuntando a las mejores prácticas para el uso de cadenas en .NET Framework :
- Use
StringComparison.Ordinal
oStringComparison.OrdinalIgnoreCase
para las comparaciones como su valor predeterminado seguro para la coincidencia de cadenas cultural-agnostic. - Utilice comparaciones con
StringComparison.Ordinal
oStringComparison.OrdinalIgnoreCase
para obtener un mejor rendimiento. - Utilice los valores no lingüísticos
StringComparison.Ordinal
oStringComparison.OrdinalIgnoreCase
lugar de las operaciones de cadena basadas enCultureInfo.InvariantCulture
cuando la comparación es lingüísticamente irrelevante (simbólica, por ejemplo).
Y finalmente:
- No utilice operaciones de cadena basadas en
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.
Aquí hay un ejemplo en el que 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á falso, y equals2 será verdadero.
Aunque la pregunta es acerca de la igualdad , para una referencia visual rápida, aquí el orden de algunas cadenas se ordenó utilizando 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
yen-US
clasifican de la misma manera -
Invariant
solo clasificass
yß
diferente de las tres culturas anteriores -
da-DK
clasifica de manera muy diferente - La bandera
IgnoreCase
importante para todas las culturas muestreadas.
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));
}
Invariante es un tipo de comparación lingüísticamente apropiado.
Ordinal es un tipo binario de comparación. (Más rápido)
Ver siao2.com/2004/12/29/344136.aspx
No es necesario utilizar ejemplos de caracteres de fantasía de Unicode para mostrar la diferencia. Este es un ejemplo simple que descubrí hoy que es sorprendente, y consiste en solo caracteres ASCII.
Según la tabla ASCII, 0
(0x48) es más pequeño que _
(0x95) cuando se compara de manera ordinaria. InvariantCulture diría lo contrario (código PowerShell a continuación):
PS> [System.StringComparer]::Ordinal.Compare("_", "0")
47
PS> [System.StringComparer]::InvariantCulture.Compare("_", "0")
-1
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, y luego si es necesario (y solicitado) se distingue por caso después de comparar primero solo en las distintas letras. (Por supuesto, también puede hacer una comparación que no distinga entre mayúsculas y minúsculas, 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 acentos y luego contabilizándolos si las letras generales coinciden (tanto como con un caso diferente, excepto que no se ignoran en última instancia en una comparación que no distingue entre mayúsculas y minúsculas). Esto agrupa las versiones acentuadas de la misma palabra, por lo demás, cerca de la otra, en lugar de separarse completamente en la primera diferencia de acento. Este es el orden de clasificación que normalmente encontraría en un diccionario, con las palabras en mayúsculas que aparecen justo al lado de sus equivalentes en minúsculas, y las letras acentuadas están cerca de la letra correspondiente sin acentos.
Una comparación ordinal se compara estrictamente con los valores de caracteres numéricos, deteniéndose en la primera diferencia. Esto ordena las letras mayúsculas completamente separadas de las letras minúsculas (y las letras acentuadas presumiblemente separadas de esas), por lo que las palabras mayúsculas no se clasificarían en ninguna parte 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 en minúsculas (un remanente de ASCII de los viejos tiempos antes de que las computadoras tuvieran letras minúsculas, las 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"
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.
Siempre intente usar InvariantCulture en aquellos métodos de cadena que lo acepten como sobrecarga. Al usar InvariantCulture estás en un lado seguro. Es posible que muchos programadores .NET no utilicen esta funcionalidad, pero si su software será utilizado por diferentes culturas, InvariantCulture es una característica extremadamente útil.