Cómo unir una lista de cadenas en CSV en C#: análisis bajo el capó

Entrenador de Python en Línea para Principiantes

Aprende Python fácilmente sin sobrecargarte de teoría. Resuelve tareas prácticas con verificación automática, recibe pistas y escribe código directamente en el navegador, sin instalar nada.

Start Course

Introducción: Por qué unir cadenas no es simplemente "sumar"

\n\n

Imagine: está escribiendo un servicio web en C# que recibe una lista de etiquetas de un usuario y debe enviarlas a la base de datos como una sola cadena separada por comas. O está generando un informe CSV para exportar. O está registrando un conjunto de identificadores. ¿Le suena familiar? La pregunta "Creating a comma separated list from IList or IEnumerable" en Stack Overflow ha acumulado miles de visitas, y no es casualidad.

\n\n

Podría parecer sencillo: tomar una lista de cadenas, recorrerla con un bucle y añadir comas. Pero en la práctica, esta tarea esconde varios escollos: desde comas sobrantes al final hasta una caída catastrófica del rendimiento con grandes volúmenes de datos. En este artículo no solo mostraremos soluciones listas, sino que exploraremos bajo el capó de cada una. Aprenderá cómo funcionan string.Join, StringBuilder e incluso LINQ Aggregate, y sabrá elegir la herramienta adecuada para su tarea.

\n\n

¡Allá vamos!

\n\n

El problema: Una consulta simple, dificultades no evidentes

\n\n

Supongamos que tenemos una colección de cadenas:

\n\n
IEnumerable<string> fruits = new List<string> { "Apple", "Banana", "Cherry", "Date" };
\n\n

Queremos obtener: "Apple,Banana,Cherry,Date". Lo primero que se le ocurre a un principiante es escribir un bucle:

\n\n
string result = "";\nbool first = true;\nforeach (var fruit in fruits)\n{\n    if (!first)\n        result += ",";\n    result += fruit;\n    first = false;\n}
\n\n

Este código funciona, pero lo hace terriblemente mal. ¿Por qué? Porque las cadenas en C# son inmutables. Cada operación += crea una nueva cadena en memoria, copiando el contenido de la anterior. Con 4 elementos es imperceptible, pero con 10,000 cadenas obtendrá una complejidad cuadrática O(n²) y un consumo de memoria gigantesco. Bajo el capó: miles de asignaciones y recolecciones de basura.

\n\n

Obviamente, se necesita un enfoque más inteligente. Y aquí entran en escena los protagonistas principales.

\n\n

Método 1: string.Join — el rey del rendimiento

\n\n

La forma más correcta y eficiente es usar el método estático string.Join:

\n\n
string csv = string.Join(",", fruits);\nConsole.WriteLine(csv); // Apple,Banana,Cherry,Date
\n\n

Una línea de código y el trabajo está hecho. Echemos un vistazo bajo el capó de string.Join (en .NET Core / .NET 5+).

\n\n

¿Qué sucede internamente?

\n
    \n
  • Cálculo de longitud: El método primero recorre toda la colección (si es IEnumerable<T>) para conocer el número total de caracteres. Si la colección es un array o un IList, obtiene la longitud directamente mediante Count.
  • \n
  • Asignación de búfer: Se asigna un único array grande de caracteres (char[]) del tamaño necesario: suma de las longitudes de todas las cadenas + (número de cadenas - 1) * longitud del separador.
  • \n
  • Copia: Todas las cadenas y separadores se copian en este búfer sin una sola asignación adicional.
  • \n
  • Creación de la cadena: A partir del búfer se crea una única cadena final.
  • \n
\n\n

Resultado: una asignación de memoria (para la cadena final) + asignación del búfer temporal. Sin cadenas intermedias. Complejidad estrictamente O(n).

\n\n

Para IList<string>, el método funciona aún más rápido, ya que puede obtener directamente Count y la longitud de cada elemento mediante el indexador, sin llamar a GetEnumerator.

\n\n

Método 2: StringBuilder — el viejo amigo

\n\n

Antes de la aparición del optimizado string.Join (o si está atascado en una versión antigua de .NET Framework), la solución estándar era StringBuilder:

\n\n
var sb = new StringBuilder();\nbool first = true;\nforeach (var fruit in fruits)\n{\n    if (!first)\n        sb.Append(',');\n    sb                

Blogs

Book Recommendations