En .Net tenemos una función llamada StartsWith para saber si un String comienza con una serie de caracteres determinados, en principio, yo me imagino que si dicha función determina que el primer carácter ya no coincide dejará de comparar el resto y devolverá un false, no obstante he querido comprobar si eso es cierto comparando cuánto tarda con un String con el que si empieza, con otro con el que no empieza o con uno con el que coincide a medias; y para que no haya dudas, un poco a lo bestia… metiéndolo en un bucle de 5 millones de pasadas.
| Bucle | Segundos |
| StartsWith No Coincidente | 1,789597 |
| StartsWith Casi Coincidente | 2,186570 |
| StartsWith Coincidente | 0,081005 |
Me sorprende que el coincidente sea el que menos consuma, ¿significa eso que .Net sigue comparando el resto de caracteres? Pero lo que me deja sin explicación alguna es ver que el coincidente a medias es el que más tiempo tarda… podrÃa pensar que este string es más largo que el anterior y tendrÃa sentido, pero serÃa absurdo pensar que el algoritmo StartsWith sigue comparando caracteres aunque ya haya encontrado uno no coincidente… ¿No les enseñaron a usar el Exit While?
Y ya que estoy, lo comparo con el Contains y…
| Bucle | Segundos |
| Contains No Coincidente | 1,015006 |
| Contains Casi Coincidente | 1,025467 |
| Contains Coincidente | 1,116619 |
Parece que el Contains está bastante mejor optimizado, parece un absurdo ya que el StartsWith lo tiene más fácil, pero los resultados no engañan. Las diferencias en este caso son menores pero se aprecia que el No Coincidente tarda menos que el Coincidente a Medias, que a su vez tarda menos que el Coincidente, lo que darÃa sentido a la teorÃa de que deja de comparar chars en cuanto uno rompe la equivalencia. El StarsWith coincidente sà consume menos, pero usarlo conlleva el riesgo de topar con un no coincidente y tardar más.
¿Y el EndsWith? ¿Funcionará igual?
| Bucle | Segundos |
| EndsWith No Coincidente | 3,723053 |
| EndsWith Casi Coincidente | 3,722809 |
| EndsWith Coincidente | 0,081173 |
Bueno, lo del EndsWith ya resulta hasta triste, no sólo es el que más tarda si no que además vuelve a demostrar que no parece que hayan sabido hacer un algoritmo con lógica. Al ser un EndsWith tendrÃan que comparar los strings a la inversa, desde atrás hacia adelante, y saliendo del bucle en cuanto encontrase el primer char no coincidente, pero por los resultados obtenidos mas parece que se ponga a buscar a Wally y a tomarse una cerveza por el camino… ahora sólo faltarÃa hacer lo mismo en C# para ver si funciona mejor, de hacerlo, el mito del C# resultarÃa cierto… pero creo que no me atrevo a desmitificar mi querido Visual Basic. Oh Microsoft, ¿por qué nos has abandonado?
Aquà va el código por si queréis verlo por vosotros mismos o podéis encontrar en dónde me he equivocado para obtener estos incomprensibles resultados (que dado que ya me equivoqué con el experimento del otro dÃa, no serÃa nada raro):
Private Sub PruebaRendimiento_StartsWith()
Dim i As Double
Dim META As Double = 5000000
Dim strPalabra As String = "escalifragilisticoespialidoso"
Dim strCoincide As String = "escalifragilisticoespialidoso"
Dim strCoincidenteAMedias As String = "escalifragilistPosVaSerQueNo"
Dim strNoCoincide As String = "PosVaSerQueNo"
Me.Trace.IsEnabled = True
Me.Trace.Warn("PRUEBA DE RENDIMIENTO. START:")
'**************************
'STARTSWITH:
'No
Me.Trace.Warn("Empiezo bucle StartsWith no coincidente.")
For i = 0 To META
If strPalabra.StartsWith(strNoCoincide) Then
End If
Next
Me.Trace.Warn("Bucle StartsWith no coincidente terminado.____________________________")
'Casi
Me.Trace.Warn("Empiezo bucle StartsWith casi coincidente.")
For i = 0 To META
If strPalabra.StartsWith(strCoincidenteAMedias) Then
End If
Next
Me.Trace.Warn("Bucle StartsWith casi coincidente terminado.____________________________")
'Si
Me.Trace.Warn("Empiezo bucle StartsWith coincidente.")
For i = 0 To META
If strPalabra.StartsWith(strCoincide) Then
End If
Next
Me.Trace.Warn("Bucle StartsWith coincidente terminado.____________________________")
'**************************
'CONTAINS:
'No
Me.Trace.Warn("Empiezo bucle Contains no coincidente.")
For i = 0 To META
If strPalabra.Contains(strNoCoincide) Then
End If
Next
Me.Trace.Warn("Bucle Contains no coincidente terminado.____________________________")
'Casi
Me.Trace.Warn("Empiezo bucle Contains casi coincidente.")
For i = 0 To META
If strPalabra.Contains(strCoincidenteAMedias) Then
End If
Next
Me.Trace.Warn("Bucle Contains casi coincidente terminado.____________________________")
'Si
Me.Trace.Warn("Empiezo bucle Contains coincidente.")
For i = 0 To META
If strPalabra.Contains(strCoincide) Then
End If
Next
Me.Trace.Warn("Bucle Contains coincidente terminado.____________________________")
'**************************
'ENDSWITH:
strCoincidenteAMedias = "PosNoticoespialidoso"
'No
Me.Trace.Warn("Empiezo bucle EndsWith no coincidente.")
For i = 0 To META
If strPalabra.EndsWith(strNoCoincide) Then
End If
Next
Me.Trace.Warn("Bucle EndsWith no coincidente terminado.____________________________")
'Casi
Me.Trace.Warn("Empiezo bucle EndsWith casi coincidente.")
For i = 0 To META
If strPalabra.EndsWith(strCoincidenteAMedias) Then
End If
Next
Me.Trace.Warn("Bucle EndsWith casi coincidente terminado.____________________________")
'Si
Me.Trace.Warn("Empiezo bucle EndsWith coincidente.")
For i = 0 To META
If strPalabra.EndsWith(strCoincide) Then
End If
Next
Me.Trace.Warn("Bucle EndsWith coincidente terminado.____________________________")
End Sub




Declaraste las strings como literals entonces .Net almanece “escalifragilisticoespialidoso” y strPalabra es una referencia a esta string. Al llegar a la declaracion de strCoincide encuentra que ya tiene el “escalifragilisticoespialidoso” entonces le da a strCoincide al misma referencia. La comparacion en el caso coincidente entonces se limite a compara las referencias. Esa posibilidad se basa en la inmutabilidad de String.