2009-05-29 15 views
0

So habe ich eine Sammlung von Razzies aus einer Sammlung von Bloops erstellt. Ich erhalte diese Sammlung mit einer Linq-Abfrage. Referenz: Linq Select Certain Properties Into Another Object? für die Abfrage.Führen Sie eine Methode für alle Objekte innerhalb einer Sammlung

Ich würde gerne wissen, ob es möglich ist, eine Methode auf allen neu erstellten Razzies vor der Rückgabe der Sammlung oder sogar direkt danach, ohne eine For-Schleife zu verwenden.

Ich versuchte dies:

Dim results = From item In bloops _ 
       Select New Razzie() With _ 
       { _ 
        .FirstName = item.FirstName, _ 
        .LastName = item.LastName _ 
       }.UpdateAddress(item.Address) 

Aber es gibt nichts zurück.

Antwort

2

Russ, könnte dies tun, was Sie wollen. Es ist ein ziemlich einfacher Ansatz. Wenn dies nicht gewünscht ist, erweitern Sie bitte Ihre Frage.

Dadurch wird die Methode für jedes Element beim Aufzählen über sie ausgeführt. Es wird nicht die Methode ausführen, bis Sie aufzählen, aber Sie können sicher wissen, dass die Methode ausführen wird, bevor Sie die Daten verwenden.

BEARBEITEN Da Sie eine versiegelte 3rd-Party-Klasse verwenden, verwenden Sie Erweiterungsmethoden. Dafür sind sie da. ;) Modifizierter Code zur Verwendung von Erweiterungsmethoden.

class MyArgs { } 
class Razzie //pretend this is a 3rd party class that we can't edit 
{ 
    public string FirstName { get; set; } 
    public string LastName { get; set; } 
} 
static class RazzieExtensions 
{ 
    public static Razzie MyMethod(this Razzie razzie, MyArgs args) 
    { 
     razzie.FirstName = razzie.FirstName.ToUpper(); 
     return razzie; 
    } 
} 
class Program 
{ 
    static void Main(string[] args) 
    { 
     var bloops = new List<Razzie> 
      { 
       new Razzie{FirstName = "name"}, 
       new Razzie{FirstName = "nAmE"} 
      }; 
     var myArgs = new MyArgs(); 
     var results = from item in bloops 
         select new Razzie 
         { 
          FirstName = item.FirstName, 
          LastName = item.LastName 
         }.MyMethod(myArgs); 

     foreach (var r in results) 
      Console.WriteLine(r.FirstName); 
     Console.ReadKey(); 
    } 
} 
+0

Dieses "würde" funktionieren, aber in meinem echten Code ist die Razzie-Klasse Teil einer Bibliothek, für die ich keine Quelle habe, daher ist "MyMethod" eine Leere und gibt nichts zurück. –

+0

oh gut, dann habe ich zwei Worte für dich: Erweiterungsmethode – dss539

+0

oder warte ... "habe keine Quelle für" oder "habe keine Quelle für und ist versiegelt"? Wenn Sie die Quelle einfach nicht haben, erben Sie einfach von Razzie und erweitern Sie es. Wenn die Klasse versiegelt ist, verwenden Sie eine Erweiterungsmethode. – dss539

0

Ich bin mir nicht sicher, was Sie mit RunVoid meinen. Void schlägt keine Rückkehr vor, aber Sie ordnen die Ergebnisse einem Wert zu.

Führen Sie RunVoid aus, um eine Methode für jedes Element auszuführen, und geben Sie dann die ursprüngliche Sammlung zurück? Wenn ja, gibt es keine integrierte Methode, aber Sie können eine solche hinzufügen.

<Extension> 
Public Function RunVoid(Of T)(source As IEnumerable(Of T), del As Action(Of T) As IEnumerable(Of T) 
    For Each cur in source 
    del(cur) 
    Next 
    return source 
End Function 
+0

Ja, ich bin versucht, die Methode auf Vorabend laufen ry item, dann die ursprüngliche Sammlung zurückgeben. Der Grund dafür ist, dass die Methode einige "Read-Only" -Eigenschaften setzt, auf die ich ansonsten nicht direkt zugreifen kann. Sie sagen also, ich bin mit einer Schleife stecken? –

+0

@Russ, Sie sind mit der Definition der Schleife einmal stecken. Nachdem Sie RunVoid definiert haben, können Sie es für jede Sammlung aufrufen, die IEnumerable (Of T) implementiert.Wenn Sie es in ein Modul in Ihrer Anwendung einfügen, sollte Ihr Beispiel kompilieren und ausführen – JaredPar

1

Verwenden Sie eine foreach-Schleife nach der ersten Verarbeitung ist der normale Weg, dies zu tun. Wenn Sie keine foreach-Schleife verwenden möchten, müssen Sie für diese Situation eine eigene Erweiterungsmethode definieren.

+0

Das einzige Problem, das ich damit habe, ist, dass ich auf eine Eigenschaft der ursprünglichen Klasse bloop zugreifen muss (ich aktualisierte meinen Code zu reflektieren), also wäre ich beschränkt auf eine verschachtelte Schleife? In diesem Fall müsste ich für die Leistung den Linq Call alle zusammen loswerden? –

0

Warum nicht einfach die normale, unbewertete Art und Weise? Sie können eine Reihe von ausgefallenen Sachen mit Erweiterungsmethoden machen ... aber Sie werden wahrscheinlich die Reinheitsregel brechen, indem Sie ein Update mit einer Erweiterungsmethode durchführen ... und es macht die Dinge auch schwierig zu verstehen. Versuchen Sie folgendes:

var results = from ... select new { Address = item.Address, Razzie = new Razzie { ... }} 

foreach (var result in results) 
{ 
    result.Razzie.UpdateAddress(result.Address); 
} 
+0

, weil ich item.Address als meine Eingabe brauche, da die Address-Eigenschaft schreibgeschützt ist. –

+0

Mein Beispiel erklärt das. – jrista

0

Wenn Sie die foreach-Schleife zu abstrahieren suchen, ich würde nur eine Erweiterungsmethode für IEnumerable <T> schreiben, die Liste <T> ‚s ConvertAll und ForEach Methoden dupliziert, wie diese :

public static IEnumerable<TOutput> ConvertAll<T, TOutput>(this IEnumerable<T> collection, Converter<T, TOutput> converter) 
{ 
    if (converter == null) 
     throw new ArgumentNullException("converter"); 

    List<TOutput> list = new List<TOutput>(); 

    foreach (T item in collection) 
    { 
     list.Add(converter(item)); 
    } 

    return list; 
} 

public static void ForEach<T>(this IEnumerable<T> collection, Action<T> action) 
{ 
    foreach (T item in collection) 
    { 
     action(item); 
    } 
} 

Dann rufen konnte man nur so etwas wie:

bloops 
    .ConvertAll(bloop => new Razzie() 
          { 
           FirstName = bloop.FirstName, 
           Lastname = bloop.LastName 
          }) 
    .ForEach(razzie => razzie.UpdateAddress()); 
Verwandte Themen