Question

En C #, j'essaie de créer une méthode d'extension pour StringBuilder appelée AppendCollection () qui me permettrait de le faire:

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 se retrouverait avec une ligne pour chaque personne de la liste. Chaque ligne serait le résultat de p.ToString (). De même pour stringOrders. Je ne sais pas trop comment écrire le code pour que les lambdas fonctionnent avec les génériques.

Était-ce utile?

La solution

Utilisez le Func<T,string> délégué.

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

Autres conseils

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

Je ne renverrais pas de chaîne, je l'ajouterais simplement au constructeur de chaînes d'origine qui a été transmis.

Je ne suis pas sûr que vous deviez travailler si dur:

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

Utilisé comme

 List<Person> people = ...

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

Bien entendu, Person doit redéfinir ToString () pour générer le résultat correct pour un objet Person.

Quelque chose comme:

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

J'ajouterais une valeur par défaut utile pour enregistrer en spécifiant le lambda dans 90% des cas ...

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

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

mais vous ne devriez pas retourner de chaîne dans ce cas. Je préférerais ce qui suit:

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

à utiliser comme:

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

  }
}

Cependant, je pense que vous feriez mieux de lui renvoyer le StringBuilder. De cette façon, vous pouvez l'enchaîner:

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

  }

string peopleAndOrders =            sb.AppendCollection (personnes, p = > p.ToString ())              .AppendCollection (orders, o = & Gt; o.ToString ()). ToString ();

Et je suis d'accord avec Jennifer sur le cas par défaut:

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

string peopleAndOrders =            sb.AppendCollection (people) .AppendCollection (orders) .ToString ();

Quelle est cette méthode supposée revenir? Je peux voir une chaîne, mais pourquoi, si vous ajoutez à StringBuilder?

Ce que vous essayez de faire est plutôt facile, mais vous devez expliquer exactement ce que vous voulez.

Mise à jour:

Voici mon point de vue. Utiliser une méthode d'extension pour cela est stupide et inutile si vous voulez simplement passer un nouveau StringBuilder et retourner une chaîne.

Mise à jour 2:

Maintenant que je vois cette utilisation, ce que vous faites est une mauvaise pratique. Ce que vous devriez idéalement faire est quelque chose comme:

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

Mise à jour 3:

Après plus de précisions:

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

(identique à celui de bruno conde)

Et maintenant vous n'en avez plus vraiment besoin:)

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top