¿Cuál es generalmente mejor usar: StringComparison.OrdinalIgnoreCase o StringComparison.InvariantCultureIgnoreCase?

161

Tengo un código como este:

If key.Equals("search", StringComparison.OrdinalIgnoreCase) Then
    DoSomething()
End If

No me importa el caso. ¿Debo usar OrdinalIgnoreCase, InvariantCultureIgnoreCaseo CurrentCultureIgnoreCase?

Dave Haynes
fuente
2
Mira esto es realmente útil para este hilo. Mi sugerencia para usar ordianlignorecase para la comparación. blogs.msdn.com/b/noahc/archive/2007/06/29/…
UmaMaheswaran
Considere la respuesta altamente votada de la comparación de cadenas
Michael Freidgeim
En general, depende mucho de qué tipo de cosas estás comparando. Específicamente, si es una entrada del usuario dependiente de la cultura o cosas internas. No desea que la cultura de la PC estropee las cadenas de código interno.
Nyerguds

Respuestas:

179

Los documentos .Net más nuevos ahora tienen una tabla para ayudarlo a decidir cuál es el mejor para usar en su situación.

De " Nuevas recomendaciones de MSDN para usar cadenas en Microsoft .NET 2.0 "

Resumen: los propietarios de códigos que anteriormente usaban InvariantCulturepara la comparación de cadenas, la carcasa y la clasificación deberían considerar seriamente el uso de un nuevo conjunto de Stringsobrecargas en Microsoft .NET 2.0. Específicamente, los datos que están diseñados para ser independientes de la cultura y lingüísticamente irrelevantes deberían comenzar a especificar sobrecargas utilizando los miembros de la nueva enumeración StringComparison.Ordinalo los StringComparison.OrdinalIgnoreCasemiembros StringComparison. Estos imponen una comparación byte por byte similar a la strcmpque no solo evita errores en la interpretación lingüística de cadenas esencialmente simbólicas, sino que proporciona un mejor rendimiento.

Robert Taylor
fuente
126
Para dar un ejemplo donde difieren, considere las dos cadenas "Straße"y "STRASSE". Al usar OrdinalIgnoreCaselos Equalsretornos false, mientras que InvariantCultureIgnoreCasedice que son iguales.
Jeppe Stig Nielsen
2
Enlace actualizado: docs.microsoft.com/en-us/dotnet/standard/base-types/…
Ohad Schneider
63

Todo depende

Comparar cadenas unicode es difícil:

La implementación de búsquedas y comparaciones de cadenas Unicode en el software de procesamiento de texto debe tener en cuenta la presencia de puntos de código equivalentes. En ausencia de esta característica, los usuarios que buscan una secuencia de puntos de código en particular no podrán encontrar otros glifos visualmente indistinguibles que tengan una representación de punto de código diferente, pero canónicamente equivalente.

ver: http://en.wikipedia.org/wiki/Unicode_equivalence


Si está tratando de comparar 2 cadenas unicode sin distinción entre mayúsculas y minúsculas y quiere que funcione EN TODAS PARTES , tiene un problema imposible.

El ejemplo clásico es el i turco , que cuando está en mayúscula se convierte en İ (observe el punto)

Por defecto, el marco .Net generalmente usa CurrentCulture para funciones relacionadas con cadenas, con una excepción muy importante .Equalsque usa una comparación ordinal (byte por byte).

Esto lleva, por diseño, a las diversas funciones de cadena que se comportan de manera diferente según la cultura de la computadora.


Sin embargo, a veces queremos un "propósito general", sin distinción entre mayúsculas y minúsculas, comparación.

Por ejemplo, es posible que desee que su comparación de cadenas se comporte de la misma manera, sin importar en qué computadora esté instalada su aplicación.

Para lograr esto tenemos 3 opciones:

  1. Establezca la cultura explícitamente y realice una comparación sin distinción entre mayúsculas y minúsculas utilizando reglas de equivalencia unicode.
  2. Establezca la cultura a la Cultura Invariante y realice una comparación sin distinción entre mayúsculas y minúsculas utilizando reglas de equivalencia unicode.
  3. Use OrdinalIgnoreCase, que pondrá en mayúscula la cadena usando InvariantCulture y luego realizará una comparación byte por byte.

Las reglas de equivalencia Unicode son complicadas, lo que significa que usar el método 1) o 2) es más costoso que OrdinalIgnoreCase. El hecho de que OrdinalIgnoreCaseno realice ninguna normalización Unicode especial significa que algunas cadenas que se procesan de la misma manera en la pantalla de una computadora no se considerarán idénticas. Por ejemplo: "\u0061\u030a"y "\u00e5"ambos representan å. Sin embargo, en una comparación ordinal se considerará diferente.

El que elija depende en gran medida de la aplicación que esté creando.

  • Si estaba escribiendo una aplicación de línea de negocio que solo usaban los usuarios turcos, me aseguraría de usar el método 1.
  • Si solo necesitara una comparación simple "falsa" sin distinción entre mayúsculas y minúsculas, por ejemplo, el nombre de una columna en una base de datos, que generalmente es inglés, probablemente usaría el método 3.

Microsoft tiene su conjunto de recomendaciones con pautas explícitas. Sin embargo, es realmente importante comprender la noción de equivalencia unicode antes de abordar estos problemas.

Además, tenga en cuenta que OrdinalIgnoreCase es un tipo de bestia muy especial , que consiste en elegir un poco de un ordinal en comparación con algunos aspectos lexicográficos mixtos. Esto puede ser confuso.

Sam Azafrán
fuente
4

Supongo que depende de tu situación. Dado que las comparaciones ordinales en realidad están mirando los valores numéricos de Unicode de los caracteres, no serán la mejor opción cuando esté ordenando alfabéticamente. Sin embargo, para las comparaciones de cadenas, el ordinal sería un poco más rápido.

Bullines
fuente
1

Depende de lo que quieras, aunque me alejaría de la cultura invariable a menos que estés muy seguro de que nunca querrás localizar el código para otros idiomas. Utilice CurrentCulture en su lugar.

Además, OrdinalIgnoreCase debe respetar los números, que pueden o no ser lo que desea.

Joel Coehoorn
fuente
1
¿Alguna vez escribiste código VB6 en un entorno de lenguaje mixto? Puede crear código que se compila en una PC con la configuración regional en francés, pero no se compila en las PC con la configuración regional en inglés, porque cualquier número almacenado en los recursos del formulario utiliza el formato de la configuración regional actual. Yo diría que debes adoptar el enfoque opuesto: ten mucho cuidado cuando uses la cultura actual. Siempre piense si su sistema seguirá funcionando cuando sus datos se muevan entre culturas. Lo mismo con las zonas horarias.
Wim Coenen
Estoy de acuerdo con la respuesta "depende". aunque no sigue el bit de "números de respeto"?
Sam Saffron
-1

La respuesta muy simple es que, a menos que esté usando turco, no necesita usar InvariantCulture.

Ver el siguiente enlace:

En C #, ¿cuál es la diferencia entre ToUpper () y ToUpperInvariant ()?

TheMoot
fuente
55
Esta respuesta puede ser simple, pero también es muy incorrecta. El "yo" turco es solo un ejemplo , hay muchas más trampas posibles.
Ohad Schneider
¿Qué más escollos? Solo conozco el caso del problema turco.
HolaMundo
Sí, además del turco hay azerí. Pero eso es todo.
Jim Balter