¿Es String.Contains () más rápido que String.IndexOf ()?

Tengo un buffer de cadena de unos 2000 caracteres y necesito verificar el buffer si contiene una cadena específica.
Hará la verificación en una aplicación web ASP.NET 2.0 para cada webrequest.

¿Alguien sabe si el método String.Contains funciona mejor que el método String.IndexOf ?

// 2000 characters in s1, search token in s2 string s1 = "Many characters. The quick brown fox jumps over the lazy dog"; string s2 = "fox"; bool b; b = s1.Contains(s2); int i; i = s1.IndexOf(s2); 

Hecho de la diversión

Contains llamadas IndexOf :

 public bool Contains(string value) { return (this.IndexOf(value, StringComparison.Ordinal) >= 0); } 

Que llama a CompareInfo.IndexOf , que finalmente utiliza una implementación de CLR.

Si desea ver cómo se comparan las cadenas en el CLR, esto le mostrará (busque CaseInsensitiveCompHelper ).

IndexOf(string) no tiene opciones y Contains() utiliza una comparación Ordinal (una comparación de byte a byte en lugar de intentar realizar una comparación inteligente, por ejemplo, e con é).

Así que IndexOf será marginalmente más rápido (en teoría) ya que IndexOf irá directamente a una búsqueda de cadenas utilizando FindNLSString desde kernel32.dll (¡la potencia del reflector!).

Actualizado para .NET 4.0IndexOf ya no usa la Comparación Ordinal, por lo que Contiene puede ser más rápido. Ver el comentario a continuación.

Probablemente, no importará en absoluto. Lea esta publicación en Coding Horror;): http://www.codinghorror.com/blog/archives/001218.html

Contiene (s2) muchas veces (en mi computadora 10 veces) más rápido que IndexOf (s2) porque Contiene usa StringComparison.Ordinal que es más rápido que la búsqueda cultural que IndexOf realiza de forma predeterminada (pero que puede cambiar en http de .net 4.0 : //davesbox.com/archive/2008/11/12/breaking-changes-to-the-string-class.aspx ).

Contiene exactamente el mismo rendimiento que IndexOf (s2, StringComparison.Ordinal)> = 0 en mis pruebas, pero es más corto y deja clara tu intención.

Estoy ejecutando un caso real (en oposición a un punto de referencia sintético)

  if("=,<=,=>,<>,<,>,!=,==,".IndexOf(tmps)>=0) { 

versus

  if("=,<=,=>,<>,<,>,!=,==,".Contains(tmps)) { 

Es una parte vital de mi sistema y se ejecuta 131,953 veces (gracias a DotTrace).

Sin embargo sorpresa impactante , el resultado es lo opuesto a lo esperado

  • IndexOf 533ms.
  • Contiene 266ms.

: – /

net framework 4.0 (actualizado el 13-02-2012)

Al utilizar Reflector, puede ver que Contiene se implementa con IndexOf. Aquí está la implementación.

 public bool Contains(string value) { return (this.IndexOf(value, StringComparison.Ordinal) >= 0); } 

Entonces, Contains es probablemente un poco más lento que llamar a IndexOf directamente, pero dudo que tenga algún significado para el rendimiento real.

Si realmente quieres micro optimizar tu código, tu mejor enfoque es siempre el benchmarking.

El .NET Framework tiene una excelente implementación de cronómetro: System.Diagnostics.Stopwatch

A partir de una pequeña lectura, parece que bajo el método String.Contains simplemente llama a String.IndexOf. La diferencia es String.Contains devuelve un valor booleano mientras que String.IndexOf devuelve un entero con (-1) que representa que no se encontró la subcadena.

Sugeriría escribir una pequeña prueba con 100.000 o más iteraciones y ver por ti mismo. Si tuviera que adivinar, diría que IndexOf puede ser un poco más rápido, pero como dije solo es una suposición.

Jeff Atwood tiene un buen artículo sobre cuerdas en su blog . Se trata más de concatenación, pero puede ser útil, no obstante.

Solo como una actualización de esto, he estado haciendo algunas pruebas y proporcionando que la cadena de entrada es bastante grande, entonces el Regex paralelo es el método más rápido que he encontrado (siempre que tengas más de un núcleo, imagino)

Obteniendo la cantidad total de coincidencias, por ejemplo –

 needles.AsParallel ( ).Sum ( l => Regex.IsMatch ( haystack , Regex.Escape ( l ) ) ? 1 : 0 ); 

¡Espero que esto ayude!

Use una biblioteca de referencia, como esta reciente incursión de Jon Skeet para medirla.

Caveat Emptor

Como todas las preguntas de (micro) rendimiento, esto depende de las versiones del software que está utilizando, los detalles de los datos inspeccionados y el código que rodea la llamada.

Como todas las preguntas de (micro) rendimiento, el primer paso debe ser obtener una versión en ejecución que sea fácil de mantener. Luego, la evaluación comparativa, el perfilado y el ajuste se pueden aplicar a los cuellos de botella medidos en lugar de adivinar.

Para cualquiera que todavía esté leyendo esto, indexOf () probablemente tenga un mejor rendimiento en la mayoría de los sistemas empresariales, ¡ya que contains () no es compatible con IE!