Solo usa
string.Join(",", yourCollection)
De esta manera no necesitas el StringBuilder
y el bucle.
Adición larga sobre el caso asincrónico. A partir de 2019, no es una configuración rara cuando los datos llegan de forma asincrónica.
En caso de que sus datos estén en una recopilación asíncrona, no hay string.Join
sobrecarga IAsyncEnumerable<T>
. Pero es fácil crear uno manualmente, pirateando el código destring.Join
:
public static class StringEx
{
public static async Task<string> JoinAsync<T>(string separator, IAsyncEnumerable<T> seq)
{
if (seq == null)
throw new ArgumentNullException(nameof(seq));
await using (var en = seq.GetAsyncEnumerator())
{
if (!await en.MoveNextAsync())
return string.Empty;
string firstString = en.Current?.ToString();
if (!await en.MoveNextAsync())
return firstString ?? string.Empty;
// Null separator and values are handled by the StringBuilder
var sb = new StringBuilder(256);
sb.Append(firstString);
do
{
var currentValue = en.Current;
sb.Append(separator);
if (currentValue != null)
sb.Append(currentValue);
}
while (await en.MoveNextAsync());
return sb.ToString();
}
}
}
Si los datos llegan de forma asincrónica pero la interfaz IAsyncEnumerable<T>
no es compatible (como se menciona en los comentarios SqlDataReader
), es relativamente fácil envolver los datos en un IAsyncEnumerable<T>
:
async IAsyncEnumerable<(object first, object second, object product)> ExtractData(
SqlDataReader reader)
{
while (await reader.ReadAsync())
yield return (reader[0], reader[1], reader[2]);
}
y usarlo:
Task<string> Stringify(SqlDataReader reader) =>
StringEx.JoinAsync(
", ",
ExtractData(reader).Select(x => $"{x.first} * {x.second} = {x.product}"));
Para poder usarlo Select
, necesitará usar nuget package System.Interactive.Async
. Aquí puede encontrar un ejemplo compilable.
string.Join(",", yourCollection)
? Editar: agregado como respuesta.