2009-06-23 11 views
13

Jest to długi strzał, wiem ...Używanie Linq do uruchomienia metody na zbiorze obiektów?

Powiedzmy mam kolekcję

List<MyClass> objects; 

i chcę uruchomić tej samej metody na każdym obiekcie w kolekcji, z lub bez powrotu wartość. Przed Linq bym powiedział:

List<ReturnType> results = new List<ReturnType>(); 
List<int> FormulaResults = new List<int>(); 
foreach (MyClass obj in objects) { 
    results.Add(obj.MyMethod()); 
    FormulaResults.Add(ApplyFormula(obj)); 
} 

bym miłość, aby móc zrobić coś takiego:

List<ReturnType> results = new List<ReturnType>(); 
results.AddRange(objects.Execute(obj => obj.MyMethod())); 
// obviously .Execute() above is fictitious 
List<int> FormulaResults = new List<int>(); 
FormulaResults.AddRange(objects.Execute(obj => ApplyFormula(obj))); 

nie znalazłem nic, że będzie to zrobić. Czy jest coś takiego?

Jeśli nic generic jakbym zakładał powyżej, przynajmniej może istnieje sposób, robi to dla celów pracuję teraz na: Mam kolekcję jednego obiektu, który ma klasy otoki:

class WrapperClass { 
    private WrappedClass wrapped; 
    public WrapperClass(WrappedClass wc) { 
    this.wrapped = wc; 
    } 
} 

Mój kod ma kolekcję List<WrappedClass> objects i chcę ją przekonwertować na List<WrapperClass>. Czy jest jakiś sprytny LINQ sposób to zrobić, nie robiąc żmudny

List<WrapperClass> result = new List<WrapperClass>(); 
foreach (WrappedClass obj in objects) 
    results.Add(new WrapperClass(obj)); 

Dzięki ...

Odpowiedz

17

Would:

results.AddRange(objects.Select(obj => ApplyFormula(obj))); 

zrobić?

lub (prostsze)

var results = objects.Select(obj => ApplyFormula(obj)).ToList(); 
+1

+1 Ja lubię drugi lepszy :) –

+1

OMG, to było takie proste ?? Cudowny! Uwielbiam LINQ !!! –

4

myślę, że Wybierz() Metoda rozszerzenie może zrobić to, czego szukasz:

objects.Select(obj => obj.MyMethod()).ToList(); // produces List<Result> 

objects.Select(obj => ApplyFormula(obj)).ToList(); // produces List<int> 

samo dla ostatnim przypadku:

objects.Select(obj => new WrapperClass(obj)).ToList(); 

Jeśli masz metodę void, do której chcesz zadzwonić, oto sztuczka, której możesz użyć z IEnumerable, która nie ma rozszerzenia ForEach(), aby stworzyć podobne zachowanie bez dużego nakładu pracy.

objects.Select(obj => { obj.SomeVoidMethod(); false; }).Count(); 

The Select() wytworzy ciąg [false] wartości po wywołaniu SomeVoidMethod() każdego [obj] w sekwencji obiektów. Ponieważ Select() używa odroczonego wykonywania, nazywamy rozszerzenie Count(), aby wymusić ocenę każdego elementu w sekwencji. Działa całkiem nieźle, gdy chcesz zachować coś takiego jak zachowanie ForEach().

1

Kompilator C# mapuje zaznaczenie LINQ na metodę rozszerzenia .Select, zdefiniowaną przez IEnumerable (lub IQueryable, które zignorujemy tutaj). Właściwie ta metoda wyboru jest dokładnie taką właśnie funkcją projekcyjną, o którą się staracie.

LBushkin jest poprawna, ale rzeczywiście można używać składni LINQ, jak również ...

var query = from o in objects 
    select o.MyMethod(); 
2

Jeśli metoda MyMethod że chcesz zastosować zwraca obiekt typu T następnie można uzyskać z następujących IEnumerable<T> rezultatem tej metody poprzez:

var results = objects.Select(o => o.MyMethod()); 

Jeśli metoda MyMethod że chcesz zastosować ma typ void powrócić następnie można zastosować metodę poprzez:

objects.ForEach(o => o.MyMethod()); 

Zakłada się, że objects ma ogólną konstrukcję List<>. Jeśli wszystko, co masz, to roll your ownForEach, możesz najpierw zastosować metodę rozszerzenia lub zastosować objects.ToList() i użyć powyższej składni.

0

Można również uruchomić niestandardową metodę przy użyciu cudowny Jon Skeet na morelinq library

Na przykład jeśli miał właściwość tekstu na MojaKlasa, że ​​trzeba było zmienić w czasie wykonywania przy użyciu metody o tej samej klasy:

objects = objects.Pipe<MyClass>(class => class.Text = class.UpdateText()).ToList(); 

Ta metoda zostanie teraz zaimplementowana na każdym obiekcie na liście. Uwielbiam morelinq!

Powiązane problemy