2012-02-03 8 views
8

Duplicar posible:
Why is String.Concat not optimized to StringBuilder.Append?¿Por qué la concatenación de cadenas no se convierte automáticamente a StringBuilder en C#?

Un día estaba despotricando sobre un control en particular Telerik a un amigo mío. Le dije que me tomó varios segundos generar un árbol de controles, y después de crear perfiles descubrí que está utilizando una concatenación de cadenas en un bucle en lugar de un StringBuilder. Después de volver a escribir, funcionó casi instantáneamente.

Así que mi amigo escuchó eso y pareció sorprenderse de que el compilador de C# no hiciera esa conversión automáticamente como lo hace el compilador de Java. Al leer muchas de las respuestas de Eric Lippert, me doy cuenta de que esta característica no llegó porque no se consideró digna. Pero si, hipotéticamente, los costos eran pequeños para implementarlo, ¿qué lógica impediría que alguien lo hiciera?

+2

No hay nada técnicamente que le impida realizar esta optimización, pero considere que las dos operaciones no son semánticamente equivalentes. Concatenar una 'cadena' devuelve un nuevo objeto' cadena' que es el resultado de la operación, mientras que usar 'StringBuilder' modificará el objeto de cadena existente. El análisis de código tendría que realizarse para asegurarse de que de ninguna manera dependía de los efectos secundarios de la concatenación. En la mayoría de los casos, no es así, no es un problema que es imposible de superar, pero, de nuevo, no es tan difícil escribir el código correctamente en primer lugar. –

+1

Vea también http://blogs.msdn.com/b/ericlippert/archive/2011/07/19/strings-immutability-and-persistence.aspx – SLaks

+1

tenga en cuenta esta publicación también: http: //pranayamr.blogspot. com/2011/02/why-to-user-stringbuilder-over-string.html –

Respuesta

9

observo que esto es un duplicado exacto de

Why is String.Concat not optimized to StringBuilder.Append?

por lo que probablemente se debe cerrar.

Pero si, hipotéticamente, los costos eran pequeños para implementarlo, ¿qué fundamento impediría que uno lo hiciera?

Parece que está proponiendo un poco de tautología: si no hay ninguna razón para no hacer X, ¿hay alguna razón para no hacer X? No.

Veo poco valor en conocer las respuestas a preguntas hipotéticas y contrafactuales. Tal vez una mejor pregunta sería una pregunta sobre el mundo real:

idiomas

¿Hay programas que utilizan esta optimización?

Sí. En JScript.NET, detectamos concatenaciones de cadenas en bucles y el compilador las convierte en llamadas a un generador de cadenas.

que podrían luego ser seguido con:

¿Cuáles son algunas de las diferencias entre JScript .NET y C# que justifican la optimización en el un idioma, pero no en el otro?

Asunción principal de JScript.NET es que sus programadores serán en su mayoría programadores de JavaScript, y muchos de ellos ya habrán creado bibliotecas que se deben ejecutar en cualquier implementación de ECMAScript. Es posible que esos programadores no conozcan bien el .NET Framework, e incluso si lo hacen, es posible que no puedan usar StringBuilder sin hacer que el código de su biblioteca no sea portátil. También es razonable suponer que los programadores de JavaScript pueden ser programadores novatos o programadores que llegaron a la programación a través de su línea de negocio en lugar de un curso de estudio en ciencias de la computación.

programadores de C# son mucho más propensos a conocer el marco .NET bien, para escribir bibliotecas que trabajan con el marco, y para ser programadores experimentados que entienden por qué bucle concatenación de cadenas es O (n) en la implementación ingenua . Necesitan esta optimización generada por el compilador menos porque pueden hacerlo ellos mismos si lo consideran necesario.

En resumen: las características del compilador consisten en gastar nuestro presupuesto para agregar valor al cliente; obtienes más "por dinero" añadiendo la función a JScript.NET que lo que añades a C#.

+0

gracias por responder. No he propuesto una tautología sin embargo. A veces las características no se agregan por razones ideológicas, no solo por costos puros (para diseñar, implementar, probar). Por ejemplo, usted mismo ha declarado que C# no incluye una extensión .ForEach simplemente porque introducirá una ambigüedad innecesaria. Los costos para agregar este oneliner son minúsculos, y sin embargo, la razón fundamental no está relacionada con ellos. Pero creo que su conclusión final es un argumento satisfactorio para mi uso con mi amigo. –

+0

@RomanR .: Soy escéptico de eso. ¿Puede ofrecer un ejemplo de una decisión ideológica que en realidad no constituye una decisión basada en los costos? – Brian

+0

@Brian: el ejemplo de RomanR es bueno; podríamos hacer un método de extensión ForEach en 'IEnumerable ' por un costo muy bajo, y algunos beneficios, pero en mi opinión, no encaja con el" espíritu "de LINQ, que es evitar los efectos secundarios. Eso es "puntos en contra" de hacer la función. También hay, por supuesto, un argumento presupuestario en contra de hacerlo, a saber, el costo de oportunidad de no hacer una mejor característica. Pero los puntos en contra son puntos en contra, y no todos los puntos en contra están basados ​​en los costos. –

6

El compilador de C# es mejor que eso.

a + b + c se compila a String.Concat(a, b, c), que es más rápido de StringBuilder.
"a" + "b" se compila directamente en "ab" (útil para literales de varias líneas).

El único lugar para usar StringBuilder es cuando se concatena repetitivamente dentro de un bucle; el compilador no puede optimizar eso fácilmente.

+0

¿Es realmente más rápido independientemente del tamaño y el número de cadenas que se concatenan? – Shredderroy

+3

Eso es * exactamente * de lo que está hablando la pregunta, sin embargo: concatenando en un bucle. –

+1

@CodyGray: me cuesta creer que Java lo optimice. – SLaks

Cuestiones relacionadas