¿Podrían las comparaciones de cadenas realmente diferir en función de la cultura cuando se garantiza que la cadena no cambiará?


Estoy leyendo credenciales cifradas/cadenas de conexión de un archivo de configuración. Resharper me dice, " String.indexOf (string) es específico de la cultura aquí " en esta línea:

if (line.Contains("host=")) {
    _host = line.Substring(line.IndexOf(
        "host=") + "host=".Length, line.Length - "host=".Length);

...y así quiere cambiarlo a:

if (line.Contains("host=")) {
    _host = line.Substring(line.IndexOf("host=", System.StringComparison.Ordinal) + "host=".Length, line.Length -   "host=".Length);

El valor que estoy leyendo siempre será "host=", independientemente de dónde se pueda implementar la aplicación. ¿Es realmente sensato añadir este "Sistema"?StringComparison.Ordinal " bit?

Más importante aún, ¿podría lastimar algo (usarlo)?

Author: B. Clay Shannon, 2012-06-08

3 answers

Absolutamente. Por MSDN ( http://msdn.microsoft.com/en-us/library/d93tkzah.aspx),

Este método realiza una palabra (sensible a mayúsculas y minúsculas y sensible a la cultura) buscar usando la cultura actual.

Así que puede obtener resultados diferentes si lo ejecuta bajo una cultura diferente (a través de la configuración regional y de idioma en el Panel de control).

En este caso en particular, probablemente no tendrá un problema, pero arroje un i en la cadena de búsqueda y ejecútelo en Turquía y probablemente arruinará su día.

Véase MSDN: http://msdn.microsoft.com/en-us/library/ms973919.aspx

Estas nuevas recomendaciones y API existen para aliviar suposiciones erróneas sobre el comportamiento de las API de cadenas predeterminadas. El canónico ejemplo de errores emergentes donde los datos de cadena no lingüísticos son interpretado lingüísticamente es el" turco-I " problema.

Para casi todos los alfabetos latinos, incluido el inglés estadounidense, el carácter me (\u0069) es la versión en minúsculas del carácter I (\u0049). Este regla de carcasa se convierte rápidamente en el valor predeterminado para alguien que programa en dicha cultura. Sin embargo, en turco ("tr-TR"), existe una capital "i con un punto", carácter (\u0130), que es la versión mayúscula de i. Del mismo modo, en turco, hay una minúscula "i sin punto", o (\u0131), que se pone en mayúscula en I. Este comportamiento se produce en el azerí cultura ("az") también.

Por lo tanto, las suposiciones normalmente hecho sobre la capitalización i o las letras I minúsculas no son válidas entre todas las culturas. Si el valor predeterminado se utilizan sobrecargas para las rutinas de comparación de cadenas, que serán sujeto a variación entre culturas. Para los datos no lingüísticos, como en el siguiente ejemplo, esto puede producir resultados no deseados:

    Thread.CurrentThread.CurrentCulture = new CultureInfo("en-US")
Console.WriteLine("Culture = {0}",
   Thread.CurrentThread.CurrentCulture.DisplayName);
Console.WriteLine("(file == FILE) = {0}", 
   (String.Compare("file", "FILE", true) == 0));

Thread.CurrentThread.CurrentCulture = new CultureInfo("tr-TR");
Console.WriteLine("Culture = {0}",
   Thread.CurrentThread.CurrentCulture.DisplayName);
Console.WriteLine("(file == FILE) = {0}", 
   (String.Compare("file", "FILE", true) == 0));

Debido a la diferencia de la comparación de I, los resultados de la las comparaciones cambian cuando se cambia la cultura del hilo. Este es el salida:

Culture = English (United States)
(file == FILE) = True
Culture = Turkish (Turkey)
(file == FILE) = False

Aquí es un ejemplo sin caso:

var s1 = "é"; //é as one character (ALT+0233)
var s2 = "é"; //'e', plus combining acute accent U+301 (two characters)

Console.WriteLine(s1.IndexOf(s2, StringComparison.Ordinal)); //-1
Console.WriteLine(s1.IndexOf(s2, StringComparison.InvariantCulture)); //0
Console.WriteLine(s1.IndexOf(s2, StringComparison.CurrentCulture)); //0
 60
Author: Mark Sowul,
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-04-03 14:33:14

CA1309: UseOrdinalStringComparison

No duele no usarlo, pero " estableciendo explícitamente el parámetro a cualquiera de los StringComparison.Ordinal o StringComparison.OrdinalIgnoreCase, su código a menudo gana velocidad, aumenta la corrección y se vuelve más confiable.".


¿Qué es exactamente Ordinal, y por qué es importante para su caso?

Una operación que usa reglas de ordenación ordinales realiza una comparación basada en el valor numérico (punto de código Unicode) de cada carácter en la cadena. Una comparación ordinal es rápida pero insensible a la cultura. Cuando usa ordinal sort rules para ordenar cadenas que comienzan con caracteres Unicode (U+), la cadena U+xxxx viene antes de la cadena U+yyyy si el valor de xxxx es numéricamente menor que aaaa.

Y, como usted dijo... el valor de cadena en el que está leyendo no es sensible a la cultura, por lo que tiene sentido usar una comparación ordinal en lugar de una comparación de Palabras. Solo recuerda, Ordinal significa "esto no es sensible a la cultura".

 26
Author: m-y,
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
2012-06-07 23:51:08

Para responder a su pregunta específica: No, pero una herramienta de análisis estático no va a ser capaz de darse cuenta de que su valor de entrada nunca tendrá información específica de la configuración regional en ella.

 5
Author: 500 - Internal Server Error,
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
2012-06-07 23:55:10