mayusculas - string.compare c#
Diferencias en los métodos de comparación de cadenas en C# (11)
Comparar la cadena en C # es bastante simple. De hecho hay varias formas de hacerlo. He enumerado algunos en el bloque de abajo. De lo que tengo curiosidad son las diferencias entre ellas y cuándo debe usarse una sobre las otras ¿Debe uno evitarse a toda costa? ¿Hay más que no he enumerado?
string testString = "Test";
string anotherString = "Another";
if (testString.CompareTo(anotherString) == 0) {}
if (testString.Equals(anotherString)) {}
if (testString == anotherString) {}
(Nota: estoy buscando igualdad en este ejemplo, no menor o mayor que, pero siéntase libre de comentar sobre eso también)
Aquí están las reglas de cómo funcionan estas funciones:
stringValue.CompareTo(otherStringValue)
-
null
viene antes de una cadena - utiliza
CultureInfo.CurrentCulture.CompareInfo.Compare
, lo que significa que usará una comparación dependiente de la cultura. Esto podría significar queß
se comparará igual aSS
en Alemania, o similar
stringValue.Equals(otherStringValue)
-
null
no se considera igual a nada - a menos que especifique una opción
StringComparison
, usará lo que parece una verificación de igualdad ordinal directa, es decir,ß
no es lo mismo queSS
, en cualquier idioma o cultura
stringValue == otherStringValue
- No es lo mismo que
stringValue.Equals()
. - El operador
==
llama al método estáticoEquals(string a, string b)
(que a su vez va a unEqualsHelper
interno para hacer la comparación). - Llamar a
.Equals()
en una cadenanull
obtiene una excepción de referencianull
, mientras que en==
no.
Object.ReferenceEquals(stringValue, otherStringValue)
Solo verifica que las referencias sean iguales, es decir, no son solo dos cadenas con el mismo contenido, sino que se está comparando un objeto de cadena consigo mismo.
Tenga en cuenta que con las opciones anteriores que utilizan el método de llamadas, hay sobrecargas con más opciones para especificar cómo comparar.
Mi consejo si solo desea verificar la igualdad es decidir si desea utilizar una comparación dependiente de la cultura o no, y luego usar .Equals
o .Equals
, dependiendo de la elección.
Como dijo Ed , CompareTo se utiliza para la clasificación.
Sin embargo, hay una diferencia entre .Equals y ==.
== resuelve esencialmente el siguiente código:
if(object.ReferenceEquals(left, null) &&
object.ReferenceEquals(right, null))
return true;
if(object.ReferenceEquals(left, null))
return right.Equals(left);
return left.Equals(right);
La razón simple es la siguiente lanzará una excepción:
string a = null;
string b = "foo";
bool equal = a.Equals(b);
Y lo siguiente no lo hará:
string a = null;
string b = "foo";
bool equal = a == b;
Desde MSDN:
"El método CompareTo fue diseñado principalmente para su uso en operaciones de ordenación o alfabetización. No debe usarse cuando el propósito principal de la llamada al método es determinar si dos cadenas son equivalentes. Para determinar si dos cadenas son equivalentes, llame al método Equals. "
Sugieren utilizar .Equals
lugar de .CompareTo
cuando se busca únicamente la igualdad. No estoy seguro de si hay una diferencia entre .Equals
y ==
para la clase de string
. A veces .Equals
o Object.ReferenceEquals
lugar de ==
para mis propias clases en caso de que alguien venga más tarde y redefine el operador ==
para esa clase.
En los formularios que enumeró aquí, no hay mucha diferencia entre los dos. CompareTo
termina llamando a un método CompareInfo
que hace una comparación usando la cultura actual; Equals
es llamado por el operador ==
.
Si consideras sobrecargas, entonces las cosas se ponen diferentes. Compare
y ==
solo puede usar la cultura actual para comparar una cadena. Equals
y String.Compare
pueden tomar un argumento de enumeración StringComparison
que le permite especificar String.Compare
no hacen StringComparison
cultura o que no hacen caso de las mayúsculas. Solo String.Compare
permite especificar un CultureInfo
y realizar comparaciones utilizando un cultura diferente al de la cultura predeterminada.
Debido a su versatilidad, encuentro que uso String.Compare
más que cualquier otro método de comparación; me permite especificar exactamente lo que quiero.
No es que el rendimiento generalmente importe con el 99% de las veces que necesita hacer esto, pero si tuviera que hacer esto en un bucle varios millones de veces, le sugeriría encarecidamente que use .Equals o == porque tan pronto como encuentre un personaje eso no coincide, hace que todo salga como falso, pero si usa la función CompareTo, tendrá que averiguar qué personaje es menor que el otro, lo que lleva a un tiempo de rendimiento ligeramente peor.
Si su aplicación se ejecutará en diferentes países, le recomiendo que revise las implicaciones de CultureInfo y posiblemente use .Equals. Ya que solo escribo aplicaciones para los EE. UU. (Y no me importa si no funciona correctamente por alguien), siempre uso ==.
Puede encontrar una buena explicación y prácticas sobre los problemas de comparación de cadenas en el artículo Nuevas recomendaciones para usar cadenas en Microsoft .NET 2.0 y también en Mejores prácticas para usar cadenas en .NET Framework .
Cada uno de los métodos mencionados (y otros) tiene un propósito particular. La diferencia clave entre ellos es qué tipo de StringComparison Enumeration están utilizando de forma predeterminada. Hay varias opciones:
- Cultura actual
- CurrentCultureIgnoreCase
- Cultura invariante
- InvariantCultureIgnoreCase
- Ordinal
- OrdinalIgnoreCase
Cada uno de los tipos de comparación anteriores apunta a diferentes casos de uso:
- Ordinal
- Identificadores internos que distinguen entre mayúsculas y minúsculas
- Identificadores sensibles a mayúsculas y minúsculas en estándares como XML y HTTP
- Configuración relacionada con la seguridad que distingue entre mayúsculas y minúsculas
- OrdinalIgnoreCase
- Identificadores internos insensibles a mayúsculas
- Identificadores que no distinguen entre mayúsculas y minúsculas en estándares como XML y HTTP
- Rutas de archivos (en Microsoft Windows)
- Claves de registro / valores
- Variables de entorno
- Identificadores de recursos (manejar nombres, por ejemplo)
- Configuración relacionada con la seguridad que no distingue entre mayúsculas y minúsculas
- InvariantCulture o InvariantCultureIgnoreCase
- Algunos datos persistentes de relevancia lingüística.
- Visualización de datos lingüísticos que requieren un orden de clasificación fijo.
- CurrentCulture o CurrentCultureIgnoreCase
- Datos mostrados al usuario.
- La mayoría de la entrada del usuario
Tenga en cuenta que StringComparison Enumeration , así como las sobrecargas para los métodos de comparación de cadenas, existe desde .NET 2.0.
Método String.CompareTo (String)
Es de hecho el tipo de implementación segura del método IComparable.CompareTo . Interpretación por defecto: CurrentCulture.
Uso:
El método CompareTo fue diseñado principalmente para su uso en operaciones de ordenación o alfabetización
Así
Implementar la interfaz de IComparable necesariamente usará este método
String.Compare Method
Un miembro estático de String Class que tiene muchas sobrecargas. Interpretación por defecto: CurrentCulture.
Siempre que sea posible, debe llamar a una sobrecarga del método de comparación que incluye un parámetro StringComparison.
Método String.Equals
Anulado de la clase Objeto y sobrecargado para seguridad de tipo. Interpretación por defecto: ordinal. Darse cuenta de:
Los métodos de igualdad de la clase String incluyen los iguales estáticos , el operador estático == y el método de instancia iguales .
Clase StringComparer
También hay otra forma de lidiar con las comparaciones de cadenas, especialmente con la ordenación:
Puede usar la clase StringComparer para crear una comparación específica de tipo para ordenar los elementos en una colección genérica. Clases como Hashtable, Dictionary, SortedList y SortedList usan la clase StringComparer para propósitos de clasificación.
Si alguna vez siente curiosidad por las diferencias en los métodos BCL, Reflector es su amigo :-)
Sigo estas pautas:
Coincidencia exacta: EDITAR: Anteriormente siempre usaba el operador == sobre el principio de que dentro de Igual a (cadena, cadena) el operador == se usa para comparar las referencias de los objetos, pero parece que strA.Equals (strB) sigue siendo 1-11% más rápido en general que string.Equals (strA, strB), strA == strB y string.CompareOrdinal (strA, strB). Probé en bucle con un StopWatch en valores de cadena internados / no internados, con longitudes de cadena iguales / diferentes, y tamaños variables (1B a 5MB).
strA.Equals(strB)
Coincidencia legible por humanos (culturas occidentales, sin distinción de mayúsculas y minúsculas):
string.Compare(strA, strB, StringComparison.OrdinalIgnoreCase) == 0
Coincidencia legible por humanos (Todas las otras culturas, caso insensible / acento / kana / etc definido por CultureInfo):
string.Compare(strA, strB, myCultureInfo) == 0
Coincidencia legible por humanos con reglas personalizadas (Todas las demás culturas):
CompareOptions compareOptions = CompareOptions.IgnoreCase
| CompareOptions.IgnoreWidth
| CompareOptions.IgnoreNonSpace;
string.Compare(strA, strB, CultureInfo.CurrentCulture, compareOptions) == 0
Una gran diferencia a tener en cuenta es .Equals () lanzará una excepción si la primera cadena es nula, mientras que == no lo hará.
string s = null;
string a = "a";
//Throws {"Object reference not set to an instance of an object."}
if (s.Equals(a))
Console.WriteLine("s is equal to a");
//no Exception
if(s==a)
Console.WriteLine("s is equal to a");
Usar .Equals también es mucho más fácil de leer .
con .Equals, también obtienes las opciones StringComparison. Muy útil para ignorar el caso y otras cosas.
por cierto, esto se evaluará como falso
string a = "myString";
string b = "myString";
return a==b
Como == compara los valores de a y b (que son punteros), esto solo se evaluará como verdadero si los punteros apuntan al mismo objeto en la memoria. .Equals desreferencia los punteros y compara los valores almacenados en los punteros. a.Las ecuaciones (b) serían verdaderas aquí.
y si cambias b por:
b = "MYSTRING";
entonces a.Equals (b) es falso, pero
a.Equals(b, StringComparison.OrdinalIgnoreCase)
seria verdad
a.CompareTo (b) llama a la función CompareTo de la cadena que compara los valores en los punteros y devuelve <0 si el valor almacenado en a es menor que el valor almacenado en b, devuelve 0 si a.Equals (b) es verdadero, y > 0 de lo contrario. Sin embargo, esto distingue entre mayúsculas y minúsculas, creo que hay opciones para que ComparTo ignore mayúsculas y demás, pero no tengo tiempo para mirar ahora. Como otros ya han dicho, esto se haría para la clasificación. La comparación de la igualdad de esta manera daría lugar a gastos generales innecesarios.
Estoy seguro de que estoy dejando cosas fuera, pero creo que esta información debería ser suficiente para comenzar a experimentar si necesitas más detalles.
- s1.CompareTo (s2): NO usar si el propósito principal es determinar si dos cadenas son equivalentes
- s1 == s2: no se puede ignorar el caso
- s1.Equals (s2, StringComparison): emite NullReferenceException si s1 es nulo
- String.Equals (s2, StringComparison): ¡ mediante el proceso de eliminación, este método estático es el GANADOR (asumiendo un caso de uso típico para determinar si dos cadenas son equivalentes)!