C# でコレクションを追加するための StringBuilder 拡張メソッド
-
20-08-2019 - |
質問
C# で、これを可能にする AppendCollection() と呼ばれる StringBuilder の拡張メソッドを構築しようとしています。
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 は、リスト内の各人物を表す行を作成することになります。各行は p.ToString() の結果になります。stringOrders についても同様です。ラムダをジェネリックで動作させるためのコードの書き方がよくわかりません。
解決
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));
}
他のヒント
public static void AppendCollection<T>(this StringBuilder builder, IEnumerable<T> list, Func<T,string> func)
{
foreach (var item in list)
{
builder.AppendLine(func(item));
}
}
私は文字列を返さないと、私はちょうどに渡された元のStringBuilderに追加します。
私はあなたが努力する必要があるかわからない。
public static void AppendCollection( this StringBuilder builder,
ICollection collection )
{
foreach (var item in collection)
{
builder.AppendLine( Convert.ToString( item ) );
}
}
タグとして使用されます
List<Person> people = ...
StringBuilder builder = new StringBuilder();
builder.AppendCollection( people );
var s = builder.ToString();
もちろん、人は、Personオブジェクトの正しい出力を生成するためにtoString()をオーバーライドする必要があります。
のような何かます:
public static void AppendCollection<TItem>(this StringBuilder builder, IEnumerable<TItem> items, Func<TItem, string> valueSelector)
{
foreach(TItem item in items)
{
builder.Append(valueSelector(item));
}
}
私は、例の90%にラムダを指定して保存するのに便利デフォルトで追加することになります...
public static void AppendCollection<TItem>(this StringBuilder builder, IEnumerable<TItem> items)
{
AppendCollection(builder, items, x=>x.ToString());
}
私のバージョン:
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();
}
がありますが、この場合には、文字列を返すべきではありません。私は、次のことを好むだろう。
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)));
}
のように使用されます
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();
}
}
しかし、私はあなたがそれがStringBuilderのを返したほうが良いと思います。あなたはそれをチェーンことができたの方法:
static StringBuilder AppendCollection<T>(this StringBuilder sb,
IEnumerable<T> coll,
Func<T,string> action)
{
// same
return sb;
}
の文字列peopleAndOrdersの= sb.AppendCollection(人、P => p.ToString()) .AppendCollection(注文、O => o.ToString())のToString();
そして、私はデフォルトのケースについて、ジェニファーに同意します:
public static StringBuilder AppendCollection<TItem>(
this StringBuilder builder,
IEnumerable<TItem> items)
{
return AppendCollection(builder, items, x=>x.ToString());
}
の文字列peopleAndOrdersの= sb.AppendCollection(人).AppendCollection(受注).ToString();
このメソッドは何を返すと考えられますか?文字列が表示されていますが、StringBuilder に追加しているのになぜでしょうか?
やろうとしていることはかなり簡単ですが、何をしたいのかを正確に説明する必要があります。
アップデート:
これが私の見解です。新しい StringBuilder を渡して文字列を返すだけの場合、これに拡張メソッドを使用するのは愚かで無意味です。
更新 2:
その使用法を見ると、あなたがやっていることは悪い習慣です。理想的には次のようなことを行う必要があります。
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);
アップデート 3:
さらに明確にした後:
public static void AppendCollection<T>(this StringBuilder sb,
List<T> col, Func<T,string> printer)
{
col.ForEach( o => sb.AppendLine(printer(o)));
}
(これはブルーノ・コンデが言ったことと同じです)
そして今はもう本当に必要ありません:)