2008-12-09 10 views
5

In C# zum Anhang, ich versuche, eine Erweiterungsmethode für Stringbuilder zu bauen genannt AppendCollection(), die ich das machen lassen würde:Stringerweiterungsmethode eine Sammlung in C#

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 mit einem enden würde Linie für jede Person in der Liste. Jede Zeile wäre das Ergebnis von p.ToString(). Gleiches gilt für StringOrders. Ich bin mir nicht ganz sicher, wie ich den Code schreiben soll, damit die Lambdas mit Generika funktionieren.

+0

Gibt es Gründe, die Sie nicht wollen String.Join() für diesen Einsatz? – philsquared

+1

Ich möchte in der Lage sein, ein Lambda als Formatierer übergeben, so dass Sie Dinge wie sb1.AppendCollection (people, => p.FirstName + "" + p.LastName); –

Antwort

9

Verwenden Sie den Func<T,string> Delegierten.

public static void AppendCollection<T>(this StringBuilder sb, 
             IEnumerable<T> collection, Func<T, string> method) { 
    foreach(T x in collection) 
     sb.AppendLine(method(x)); 
} 
+0

Ich mag das nicht, da es das Paradigma von StringBuilder bricht. Methoden in StringBuilder sollten einfach weiter zum internen Puffer hinzugefügt werden, bis ToString für den Builder aufgerufen wird. Dies kombiniert die Append/Tostring-Schritte und ist nicht wie die anderen Append-Methoden auf StringBuilder. – tvanfosson

+0

Sicher, ich habe die Antwort aktualisiert, um meine Meinung dazu zu erwähnen, aber es wird speziell in der Frage gefragt. –

+0

stimme ich vollständig zu. Ich habe diesen Beispielcode etwas zu schnell eingegeben. Ich habe die Frage aktualisiert. –

2

Was soll diese Methode zurückgeben? Ich kann eine Zeichenfolge sehen, aber warum, wenn Sie an einen StringBuilder anhängen?

Was Sie versuchen, ist ziemlich einfach, aber Sie müssen genau erklären, was Sie wollen.

Update:

Hier ist mein nehmen. Die Verwendung einer Erweiterungsmethode ist dumm und sinnlos, wenn Sie einfach einen neuen StringBuilder übergeben und eine Zeichenfolge zurückgeben.

Update 2:

Nun, da ich sehe, dass die Nutzung, was Sie tun, schlechte Praxis. Was Sie sollten im Idealfall tun ist so etwas wie:

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:

Nach mehr Klarstellung:

public static void AppendCollection<T>(this StringBuilder sb, 
    List<T> col, Func<T,string> printer) 
{ 
    col.ForEach(o => sb.AppendLine(printer(o))); 
} 

(was dasselbe ist wie bruno conde sagte)

Und jetzt brauchst du es nicht mehr :)

+0

Also werde ich abgelehnt, weil ich um Klärung bitte? Das ist der Geist ... – leppie

+0

Ich denke, der Punkt ist, dass Ihr Beitrag keine Antwort ist, es ist eine Frage. Ich habe dich nicht abgelehnt. –

+0

Also sprach ich mit mir selbst? – leppie

3

Ich bin nicht sicher, was Sie brauchen, dass hart arbeiten:

public static void AppendCollection(this StringBuilder builder, 
             ICollection collection) 
{ 
    foreach (var item in collection) 
    { 
     builder.AppendLine(Convert.ToString(item)); 
    } 
} 

Eingesetzt als

List<Person> people = ... 

StringBuilder builder = new StringBuilder(); 
builder.AppendCollection(people); 
var s = builder.ToString(); 

Natürlich Person muss ToString() zu überschreiben die korrekte Ausgabe zu erzeugen für ein Person-Objekt.

+0

Mit dem Lambda können Sie das Element in der Sammlung formatieren, wie immer Sie möchten. –

+0

Sicher, aber Sie rufen nur ToString() – tvanfosson

+0

Ich hätte wahrscheinlich etwas wie sb1.AppendCollection (p.FirstName + "" + p.LastName) in dem Beispiel geschrieben. Das ist die Flexibilität, die ich in dieser Funktion mag. –

3

Etwas wie:

public static void AppendCollection<TItem>(this StringBuilder builder, IEnumerable<TItem> items, Func<TItem, string> valueSelector) 
    { 
     foreach(TItem item in items) 
     { 
      builder.Append(valueSelector(item)); 
     } 
    } 

ich in einem nützlichen Standard hinzufügen würde Einzelheiten enthalten das Lambda in 90% der Fälle zu retten ...

public static void AppendCollection<TItem>(this StringBuilder builder, IEnumerable<TItem> items) 
    { 
     AppendCollection(builder, items, x=>x.ToString()); 
    } 
2
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(); 

    } 
} 

Aber ich denke, Ihnen‘ Es wäre besser, wenn Sie den StringBuilder zurückgeben. Auf diese Weise konnte man die Kette es:

static StringBuilder AppendCollection<T>(this StringBuilder sb, 
            IEnumerable<T> coll, 
            Func<T,string> action) 
    { 
     // same 
     return sb; 

    } 

String peopleAndOrders = sb.AppendCollection (Menschen, p => p.ToString()) .AppendCollection (Befehle, o => o.ToString()). ToString();

Und ich stimme mit Jennifer über Standardfall:

public static StringBuilder AppendCollection<TItem>(
        this StringBuilder builder, 
        IEnumerable<TItem> items) 
    { 
     return AppendCollection(builder, items, x=>x.ToString()); 
    } 

String peopleAndOrders = sb.AppendCollection (Personen) .AppendCollection (Aufträge) .ToString();

+0

Die Verkettung Sache ist nett, aber ich bevorzuge im Allgemeinen meine Erweiterungsmethoden im Grunde funktionieren auf die gleiche Weise wie die anderen Methoden auf der Klasse. Ändern Sie das grundlegende Muster, wie es funktioniert, macht es schwerer zu verstehen. – tvanfosson

4
public static void AppendCollection<T>(this StringBuilder builder, IEnumerable<T> list, Func<T,string> func) 
     { 
      foreach (var item in list) 
      { 
       builder.AppendLine(func(item)); 
      } 
     } 

würde ich nicht einen String zurückgeben, würde ich hängen Sie ihn nur auf den ursprünglichen String, die übergeben wurde

+0

Ja, ich stimme zu.Das war ein Fehler. Ich habe die Frage aktualisiert. –

3

Meine Version.

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(); 
    } 

aber Sie sollten eine nicht zurück String in diesem Fall. Ich würde es vorziehen, die folgenden:

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))); 
    } 

wie verwendet werden:

 sb.AppendCollection(people, p => p.ToString()); 
     sb.AppendCollection(orders, o => o.ToString()); 
     Console.WriteLine(sb.ToString()); 
+0

Ich stimme zu, dass ich keine Zeichenfolge zurückgeben sollte. Ich habe die Frage aktualisiert. –