views:

84

answers:

4

I have a method like this:

public List<Fruit> Traverse (IEnumerable<Fruit> collection, Action<Fruit> action)

I can do this:

Traverse (array, f => f.Text);

How can I call the action so I get the same element?

Traverse (array, f => f);

C# compiler doesn't allow me to do this.

EDIT:

List<Fruit> result = ...
foreach (Fruit fruit in collection)
{
    result.Add(fruit);
    action(fruit);
}

The method signature is fixed so I can't get anything else by just using an action, right? But what I need is to pass an action that does nothing so I get the whole result list.

+3  A: 

Isn't Action a delegate that returns nothing? How about:

Traverse(array, e => {});
Ken
Thanks that works.
Joan Venge
Joan, that you say "that works" suggests you're doing this wrong in the first place. It sounds like you want an member access expression rather than an action. Like JaredPar said.
Craig Stuntz
Also I don't think I explained the question correctly, but updated it now.
Joan Venge
This is the right answer now that we have the right question :)
GraemeF
+1  A: 

Your method declaration doesn't seem right...

If you have this:

public List<string> Traverse (IEnumerable<string> collection, Action<string> action)

You can't be passing in this:

Traverse (array, e => e.Text);

This would require that each element support a "Text" property. String doesn't have a Text property.

If you passed an IEnumerable<string>, then e => e would evaluate to an Func<string, string>. You're returning the string itself.

If you want an Action<string>, you need to do something with the string that doesn't return a value (e).

Reed Copsey
I think I am missing a few things. I actually want to get the result list (added more code), can I do it with Action? Also when you say e => e, it returns the string itself, but then you are collecting the result of the Func inside the method, right? I collect the traversed object directly, not the action.
Joan Venge
So I guess the above code might be written better. Can you please tell me if I should use Func in this case, and if so, can you please write it using Func so I see the difference.
Joan Venge
+1  A: 

You've set up your Traverse method wrong. You need to use a generic signature here and a Func<T> return.

public List<T> Traverse (IEnumerable<T> collection, Func<T,T> del)
JaredPar
Thanks Jared. Why it's wrong? I could use generics but the traverse method has special traversing of Fruit objects. Also what's the difference between Func and Action? Which is better?
Joan Venge
Func<...> returns a value. Action<T> just performs an "action" on the object being passed in. If you want to return from the delegate, you want Func. If the delegate is just performing an "action" on each element, use Action
Reed Copsey
+1  A: 

Action<string> takes a string argument but returns nothing, similar to a method with the signature void Foo(string bar).

If you're using your action parameter to populate the return value than you will need to replace your action with Func<string, string>, which takes a string parameter and returns a string, similar to a function with the signature string Foo(string bar).

GraemeF