2009-05-13 21 views
17

Hay varias formas de comparar cadenas. ¿Hay ganancias de rendimiento al hacer una manera sobre otra?Rendimiento de comparación de cadenas en C#

siempre he optado por comparar cadenas de este modo:

string name = "Bob Wazowski"; 
if (name.CompareTo("Jill Yearsley") == 0) { 
    // whatever... 
} 

Pero encuentro pocas personas que hacen esto, y en todo caso, veo más gente simplemente haciendo una comparación == recta, lo que a mi conocimiento es la peor forma de comparar cadenas. ¿Me equivoco?

Además, ¿hace una diferencia en cómo se comparan las cadenas dentro de las consultas LINQ? Por ejemplo, me gusta hacer lo siguiente:

var results = from names in ctx.Names 
       where names.FirstName.CompareTo("Bob Wazowski") == 0 
       select names; 

Pero, de nuevo, veo pocas personas haciendo las comparaciones de cadenas como tal en sus consultas LINQ.

+0

posible duplicado de [Las diferencias en la secuencia comparan métodos en C#] (http://stackoverflow.com/questions/44288/differences-in-string-compare-methods-in-c-sharp) – crowder

+0

Es posible que desee para ver http://rhale78.wordpress.com/2011/05/16/string-equality-and-performance-in-c/ – nawfal

Respuesta

22

Según Reflector

"Hello" == "World" 

es la misma que

String.Equals("Hello", "World"); 

que básicamente determina si son el mismo objeto de referencia, si cualquiera de ellos es nula, lo que sería una automática falso si uno era nulo y el otro no, y luego compara cada personaje en un bucle inseguro. Por lo tanto, no le importan las reglas culturales en absoluto, lo que generalmente no es gran cosa.

y

"Hello".CompareTo("World") == 0 

es la misma que

CultureInfo.CurrentCulture.CompareInfo.Compare("Hello", "World", CompareOptions.None); 

Esto es básicamente lo opuesto a la medida de lo funcionalidad. Tiene en cuenta la cultura, la codificación y todo lo demás con la cadena dentro del contexto.

Así que me imagino que String.CompareTo es un par de órdenes de magnitud más lento que el operador de igualdad.

como para su LINQ no importa si está utilizando LINQ a SQL porque ambos se genere el mismo SQL

var results = from names in ctx.Names 
      where names.FirstName.CompareTo("Bob Wazowski") == 0 
      select names; 

de

SELECT [name fields] 
FROM [Names] AS [t0] 
WHERE [t0].FirstName = @p0 

por lo que realmente no está obteniendo cualquier cosa para LINQ-to-SQL excepto que es más difícil de leer el código y probablemente más análisis de las expresiones. Si solo está utilizando LINQ para material de matriz estándar, entonces se aplican las reglas que expuse arriba.

+2

string.Equals no hace una verificación de igualdad de referencia en .NET 4.0, está sobrecargado en una cadena para comparar las cadenas reales. (No me sorprendería si esto fuera siempre cierto sin embargo.) – Massif

+0

AFAIK, string.Equals también considera la cultura. –

+1

@ La respuesta de Massif es correcta. String.Equals() y == no comparan referencias de objetos. Para demostrárselo a usted mismo, llame a Object.ReferenceEquals (x, y), donde x es una cadena codificada ey en la línea de comando. – GreenRibbon

2

Hubo una pregunta bastante similar recientemente con respecto a la forma más rápida de recortar una cadena, pero básicamente se compararon las diferentes formas de compararlas.

Puede consultar los puntos de referencia on this post.

+0

Revisé la publicación. Gracias, fue útil. Acaba de reafirmar que string.length es la forma más rápida de verificar si una cadena está vacía, a menos que malinterprete los resultados del benchmark. – Jagd

15

En mi opinión, siempre debe usar la manera más clara, que es usar ==!

Esto se puede entender directamente: cuando "Hola" equivale a "Mundo", entonces haga algo.

if ("Hello" == "World") 
    // ... 

Internamente, String::Equals se invoca explícitamente que existe para este fin - La comparación de dos cadenas son iguales. (Esto no tiene nada que ver con los punteros y las referencias, etc.)

Esto no está claro de inmediato: ¿por qué comparar con cero?

if ("Hello".CompareTo("World") == 0) 

.CompareTo no está diseñado sólo para comprobar la igualdad (que ha == para esto) - Compara dos cadenas. Utiliza .CompareTo para determinar si una cadena es "mayor" que otra. Usted puede comprobar la igualdad, ya que rinde cero para cadenas iguales, pero eso no es lo que se concibe.

Por lo tanto hay diferentes métodos e interfaces para el control de la igualdad (IEquatable, == operador) y comparando (IComparable)

LINQ no se comporta diferente a la normal C# aquí.

+2

El OP no preguntaba cuál es la forma más clara de escribir una comparación de cadenas. Lo que está claro para uno puede no serlo para otro. –

8

Lea Jeff's The Best Code is No Code at All. foo.CompareTo(bar) == 0: desorden visual horrible. Ocupa mucho espacio y no transmite ningún significado interesante. De hecho, enfatiza muchas cosas irrelevantes que desvían la atención del problema real.

Si no hay un motivo bien definido para usar esta variante más larga, no lo haga.

En cuanto a rendimiento: simplemente no importa en este caso simple. Si el operador de igualdad == realmente se desempeña peor que CompareTo, siéntase libre de presentar un informe de error con Microsoft. Esto no debe suceder.

1

Si el operador de igualdad en realidad funcionó peor que CompareTo - ¿Microsoft no haría la implementación del operador de igualdad llamada CompareTo?

Simplemente use el operador de igualdad para comprobar la igualdad.

0

Generalmente uso String.Compare con la sobrecarga que toma un parámetro StringComparison, porque entonces puedo ser absolutamente explícito sobre si la comparación es sensible a mayúsculas y minúsculas o no. Esto necesita .NET 2.0 o posterior.

El más rápido es StringComparison.Ordinal (o StringComparison.OrdinalIgnoreCase si no distingue entre mayúsculas y minúsculas) para las comparaciones que no son sensibles a la cultura.

El problema con el uso de == es que no está claro si el autor ha considerado la sensibilidad de mayúsculas y minúsculas.

Hay un buen artículo de MSDN sobre el tema here.

+0

== es Igual() e Igual() que CaseSens. & CultureInsens. búsqueda (la más rápida, fácil de recordar). Calling Equals (var, StringComparison.OrdinalCaseInsensetive) es más lento que llamar a Equals(), por lo que, en caso de que se comparen millones de cadenas, es mejor utilizar Equals() simple en lugar de la versión == y 2arg. – Grigory

0

Para mejor manera de comparar string 's en C# es el uso de los a.Equals(b) donde un y b son cadenas.Esta es la mejor manera de comparar cadenas porque compara los valores de los objetos a y b, y no depende de la referencia de los objetos.

Si usted va a utilizar "==" símbolo, el resultado será igual si los dos objetos tienen la misma referencia pero tendrá un problema cuando tienen diferentes referencias y tienen el mismo valor.

El método compareTo es la mejor manera de usar si su prueba si la otra cadena se precedentes, siguiente o que aparecen en la misma posición de la otra cadena en el que se volverá valor negativo, el valor positivo o valor cero respectivamente. Se devolverá el valor también es positivo si el parámetro es null

+0

Ya está claro de las otras respuestas, pero solo para asegurarse: esto está mal. string sobrecarga el operador '==' –

4

Bueno MSDN indica que shoul utiliza la función de comparación de acuerdo a la tarea que debe realizar:

El método CompareTo fue diseñado principalmente para su uso en la clasificación o operaciones de 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.

Así que si no es sobre la clasificación y el valor retrun no es importante, diría que uno debe utilizar el:

first.Equals(second) o si la comparación es cultura específica, por ejemplo, en idiomas como en alemán:

String.Equals(first, second, StringComparison.CurrentCulture)

Tome un vistazo a estos enlaces:

How to: Compare Strings (C# Programming Guide)

String.CompareTo Method (Object)

0

Here es la guía más completa y útil de MSDN para la comparación de cadenas que he encontrado.

Use comparaciones con StringComparison.Ordinal o StringComparison.OrdinalIgnoreCase para un mejor rendimiento.

Cuestiones relacionadas