tags:

views:

161

answers:

5

This is a long shot, I know...

Let's say I have a collection

List<MyClass> objects;

and I want to run the same method on every object in the collection, with or without a return value. Before Linq I would have said:

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

I would love to be able to do something like this:

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

I haven't found anything that will do this. Is there such a thing?

If there's nothing generic like I've posited above, at least maybe there's a way of doing it for the purposes I'm working on now: I have a collection of one object that has a wrapper class:

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

My code has a collection List<WrappedClass> objects and I want to convert that to a List<WrapperClass>. Is there some clever Linq way of doing this, without doing the tedious

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

Thanks...

+5  A: 

Would:

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

do?

or (simpler)

var results = objects.Select(obj => ApplyFormula(obj)).ToList();
Marc Gravell
+1 I like the second one better :)
Andrew Hare
OMG, it was that simple?? Marvellous! I LOVE LINQ!!!
Shaul
+2  A: 

I think that the Select() extension method can do what you're looking for:

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

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

Same thing for the last case:

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

If you have a void method which you want to call, here's a trick you can use with IEnumerable, which doesn't have a ForEach() extension, to create a similar behavior without a lot of effort.

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

The Select() will produce a sequence of [false] values after invoking SomeVoidMethod() on each [obj] in the objects sequence. Since Select() uses deferred execution, we call the Count() extension to force each element in the sequence to be evaluated. It works quite well when you want something like a ForEach() behavior.

LBushkin
A: 

http://www.hookedonlinq.com/UpdateOperator.ashx has an extended Update method you can use. Or you can use a select statement as posted by others.

+1  A: 

The C# compiler maps a LINQ select onto the .Select extension method, defined over IEnumerable (or IQueryable which we'll ignore here). Actually, that .Select method is exactly the kind of projection function that you're after.

LBushkin is correct, but you can actually use LINQ syntax as well...

var query = from o in objects
   select o.MyMethod();
Martin
+2  A: 

If the method MyMethod that you want to apply returns an object of type T then you can obtain an IEnumerable<T> of the result of the method via:

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

If the method MyMethod that you want to apply has return type void then you can apply the method via:

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

This assumes that objects is of generic type List<>. If all you have is an IEnumerable<> then you can roll your own ForEach extension method or apply objects.ToList() first and use the above syntax .

Jason