tags:

views:

57

answers:

5

Hi,

I'd like to call MyMethod on each object from a LINQ Query, what is the best way to do this?

Currently I am using:

.Select(x => { x.MyMethod (); return x; }).ToArray();

ToArray() is needed for immediate execution.

Is there a simpler way to write this (without a foreach)

Thanks

+1  A: 

I created an Apply extension method :

public static IEnumerable<T> Apply<T>(this IEnumerable<T> source, Action<T> action)
{
    foreach(var item in source)
    {
        action(item);
        yield return item;
    }
}

You can use it as follows :

var results = query.Apply(x => x.MyMethod()).ToArray();

Actually, that's similar to the List<T>.ForEach method, excepts that it returns the items of the source so that you can continue to apply sequence operators on it

Thomas Levesque
+1  A: 

A for each is probably going to be the easiest way to do this, you could write an extension method that does the for each, but You really wouldn't gain anything.

msarchet
+5  A: 

You could specify your own reusable extension method that runs an Action<> on each element, and yield returns it.

IEnumerable<T> Do(this IEnumerable<T> vals, Action<T> action) {
    foreach(T elem in vals) {
        action(elem);
        yield return elem;
    }
}

Such method is included in the Rx library, under the System.Interactive namespace. Then you can simply do

myCollection.Do(x => x.MyMethod()).ToArray();
Mau
`Rx` also includes the `Run` operator, which is just like `Do` but also executes the sequence (without the overhead of storing it in an array).
Stephen Cleary
+1  A: 

xList already has the method you need: .ForEach(). It calls an Action on each list member.

List<x> fooList = ....Select(x => x).ToList();
fooList.ForEach(x => DoSomething(x));
Cylon Cat
Splendid - many thanks!
Mister Cook
You can make it simpler : `fooList.ForEach(DoSomething)`
Thomas Levesque
+1  A: 

In my opinion, you don't need to call .To___ conversion methods since you are expecting side-effects only. Reactive Extension's Do() method would be a viable option.

By using Do() method, you have two advantages (as far as I'm concerned),

1) Defer execution (You can defer the immediate execution if you want).

2) Do() method has different overloads to let you have more controls over iteration. For example: Do(onNext, OnError, OnCompeleted) overload

        var deferQuery = query.Do(x => a.MyMethod(), ex => Console.WriteLine(ex.Message), () => Console.WriteLine("Completed"));
        var immediateQuery = query.Do(x => a.MyMethod(), ex => Console.WriteLine(ex.Message), () => Console.WriteLine("Completed")).Run();
Kthurein