método de extensão StringBuilder para acrescentar uma coleção em C #
-
20-08-2019 - |
Pergunta
Em C #, eu estou tentando construir um método de extensão para StringBuilder chamada AppendCollection () que me deixaria fazer isso:
var sb1 = new StringBuilder();
var sb2 = new StringBuilder();
var people = new List<Person>() { ...init people here... };
var orders = new List<Orders>() { ...init orders here... };
sb1.AppendCollection(people, p => p.ToString());
sb2.AppendCollection(orders, o => o.ToString());
string stringPeople = sb1.ToString();
string stringOrders = sb2.ToString();
stringPeople iria acabar com uma linha para cada pessoa na lista. Cada linha seria o resultado de p.ToString (). Da mesma forma para stringOrders. Eu não tenho certeza de como escrever o código para fazer o trabalho lambdas com os genéricos.
Solução
Use o delegado Func<T,string>
.
public static void AppendCollection<T>(this StringBuilder sb,
IEnumerable<T> collection, Func<T, string> method) {
foreach(T x in collection)
sb.AppendLine(method(x));
}
Outras dicas
public static void AppendCollection<T>(this StringBuilder builder, IEnumerable<T> list, Func<T,string> func)
{
foreach (var item in list)
{
builder.AppendLine(func(item));
}
}
Eu não voltaria uma corda, gostaria apenas de acrescentar que o StringBuilder original que foi passado.
Eu não tenho certeza que você precisa para trabalho tão difícil:
public static void AppendCollection( this StringBuilder builder,
ICollection collection )
{
foreach (var item in collection)
{
builder.AppendLine( Convert.ToString( item ) );
}
}
Usado como
List<Person> people = ...
StringBuilder builder = new StringBuilder();
builder.AppendCollection( people );
var s = builder.ToString();
Claro, pessoa precisa de substituir ToString () para produzir a saída correta para um objeto Person.
Algo como:
public static void AppendCollection<TItem>(this StringBuilder builder, IEnumerable<TItem> items, Func<TItem, string> valueSelector)
{
foreach(TItem item in items)
{
builder.Append(valueSelector(item));
}
}
Gostaria de acrescentar em um padrão útil para salvar especificando o lambda em 90% dos casos ...
public static void AppendCollection<TItem>(this StringBuilder builder, IEnumerable<TItem> items)
{
AppendCollection(builder, items, x=>x.ToString());
}
Minha versão:
public static string AppendCollection<T>(this StringBuilder sb, IEnumerable<T> enumerable, Func<T, string> method)
{
List<T> l = new List<T>(enumerable);
l.ForEach(item => sb.AppendLine(method(item)));
return sb.ToString();
}
mas você não deve retornar uma string neste caso. Eu preferiria o seguinte:
public static void AppendCollection<T>(this StringBuilder sb, IEnumerable<T> enumerable, Func<T, string> method)
{
List<T> l = new List<T>(enumerable);
l.ForEach(item => sb.AppendLine(method(item)));
}
para ser usado como:
sb.AppendCollection(people, p => p.ToString());
sb.AppendCollection(orders, o => o.ToString());
Console.WriteLine(sb.ToString());
static class SBExtention
{
static string AppendCollection<T>(this StringBuilder sb,
IEnumerable<T> coll,
Func<T,string> action)
{
foreach(T t in coll)
{
sb.Append(action(t));
sb.Append("\n");
}
return sb.ToString();
}
}
No entanto, acho que vai ser melhor para tê-lo retornar o StringBuilder. Dessa forma, você poderia acorrentar-lo:
static StringBuilder AppendCollection<T>(this StringBuilder sb,
IEnumerable<T> coll,
Func<T,string> action)
{
// same
return sb;
}
peopleAndOrders string = sb.AppendCollection (pessoas, p => p.ToString ()) . .AppendCollection (encomendas, o => o.ToString ()) ToString ();
E eu concordo com Jennifer sobre o caso padrão:
public static StringBuilder AppendCollection<TItem>(
this StringBuilder builder,
IEnumerable<TItem> items)
{
return AppendCollection(builder, items, x=>x.ToString());
}
peopleAndOrders string = sb.AppendCollection (pessoas) .AppendCollection (ordens) .ToString ();
O que é este método supor para retornar? Eu posso ver uma corda, mas por que, se você está anexando a um StringBuilder?
O que você está tentando fazer é bastante fácil, mas você precisa explicar exatamente o que você quer.
Update:
Aqui é a minha opinião. Usando um método de extensão para isso é estúpido e inútil se você está indo só para passar em um novo StringBuilder e retornar uma string.
Update 2:
Agora que vejo que o uso, o que está fazendo é uma prática ruim. O que você deve idealmente fazer é algo como:
public static string Print<T>(this IEnumerable<T> col, Func<T,string> printer)
{
var sb = new StringBuilder();
foreach (T t in col)
{
sb.AppendLine(printer(t));
}
return sb.ToString();
}
string[] col = { "Foo" , "Bar" };
string lines = col.Print( s => s);
Update 3:
Depois de mais esclarecimentos:
public static void AppendCollection<T>(this StringBuilder sb,
List<T> col, Func<T,string> printer)
{
col.ForEach( o => sb.AppendLine(printer(o)));
}
(que é o mesmo quando Bruno Conde disse)
E agora você realmente não precisa mais dela:)