views:

909

answers:

10

All the examples I can find about Func<> and Action<> are simple as in the one below where you see how they technically work but I would like to see them used in examples where they solve problems that previously could not be solved or could be solved only in a more complex way, i.e. I know how they work and I can see they are terse and powerful, so I want to understand them in a larger sense of what kinds of problems they solve and how I could use them in the design of applications.

In what ways (patterns) do you use Func<> and Action<> to solve real problems?

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace TestFunc8282
{
    class Program
    {
        static void Main(string[] args)
        {
            //func with delegate
            Func<string, string> convert = delegate(string s)
            {
                return s.ToUpper();
            };

            //func with lambda
            Func<string, string> convert2 = s => s.Substring(3, 10);

            //action
            Action<int,string> recordIt = (i,title) =>
                {
                    Console.WriteLine("--- {0}:",title);
                    Console.WriteLine("Adding five to {0}:", i);
                    Console.WriteLine(i + 5);
                };

            Console.WriteLine(convert("This is the first test."));
            Console.WriteLine(convert2("This is the second test."));
            recordIt(5, "First one");
            recordIt(3, "Second one");

            Console.ReadLine();

        }
    }
}
+8  A: 

Using linq.

List<int> list = { 1, 2, 3, 4 };

var even = list.Where(i => i % 2);

The parameter for Where is an Func<int, bool>.

Lambda expressions are one of my favorite parts of C#. :)

Daniel A. White
The parameter for the `Where` method is actually a `Func<T, bool>`, not an `Action<T, bool>`.
LukeH
THanks, I'll update that.
Daniel A. White
The msdn seems to suggest it is a Func<TSource, bool> http://msdn.microsoft.com/en-us/library/bb534803.aspx
Yannick M.
@Yannick M. True. But in my example its derived from the `T` in the generic `List`.
Daniel A. White
I know, my comment was to you thinking it was an `Action<>`. An `Action` has returntype void, so it is illogical to assume it would be used in where.
Yannick M.
Oh I though you were referring to it with `TSource`
Daniel A. White
leppie
@leppie - True, but many compilers today have that internally.
Daniel A. White
+1  A: 

Actually, i found this at stackoverflow (at least - the idea):

public static T Get<T>  
    (string cacheKey, HttpContextBase context, Func<T> getItemCallback)
            where T : class
        {
            T item = Get<T>(cacheKey, context);
            if (item == null) {
                item = getItemCallback();
                context.Cache.Insert(cacheKey, item);
            }

            return item;
        }
Arnis L.
can you send original link?
Rubens Farias
No. Unfortunately i cannot. It was one of those "tips and tricks" questions.
Arnis L.
These are generics, not Func or Action. Different animal.
Alex
Sometimes i'm wondering. Do people read before they post? @Alex, check out function parameters once more.
Arnis L.
+5  A: 

One thing I use it for is Caching of expensive method calls that never change given the same input:

public static Func<TArgument, TResult> Memoize<TArgument, TResult>(this Func<TArgument, TResult> f)
{
    Dictionary<TArgument, TResult> values;

    var methodDictionaries = new Dictionary<string, Dictionary<TArgument, TResult>>();

    var name = f.Method.Name;
    if (!methodDictionaries.TryGetValue(name, out values))
    {
        values = new Dictionary<TArgument, TResult>();

        methodDictionaries.Add(name, values);
    }

    return a =>
    {
        TResult value;

        if (!values.TryGetValue(a, out value))
        {
            value = f(a);
            values.Add(a, value);
        }

        return value;
    };
}

The default recursive fibonacci example:

class Foo
{
  public Func<int,int> Fibonacci = fib;

  public Foo()
  {
    Fibonacci = Fibonacci.Memoize();

    for (int i=0; i<50; i++)
      Console.WriteLine(Fibonacci(i));
  }

  public int fib(int n)
  {
    return n > 1 ? Fibonacci(n-1) + Fibonacci(n-2) : n;
  }
}
Yannick M.
I think there's a bug here: shouldn't fib call itself, or do you mean it to call the property (which is a delegate reference to itself?)
Joel Coehoorn
It should indeed call the delegate. Otherwise you wouldn't be able to intercept the recursive calls. The idea is to encapsulate the call, so the cache actually becomes useful.
Yannick M.
However, to be quite honest, having to write plumbing code like this is fun, once, but can grow tiresome. I really like the Aspect Oriented style of tagging a method with an attribute and intercepting the Invoke alltogether. I have a post on this: http://stackoverflow.com/questions/1517206/code-generation-based-on-method-attributes
Yannick M.
+1  A: 

By keeping them geric and supporting multiple arguments and, it allows us to avoid having to create strong typed delegates or redundant delegates that do the same thing.

hjb417
+3  A: 

I use the Action and Func delegates all the time. I typically declare them with lambda syntax to save space and use them primarly to reduce the size of large methods. As I review my method, sometimes code segments that are similar will stand out. In those cases, I wrap up the similar code segments into Action or Func. Using the delegate reduces redundant code, give a nice signature to the code segment and can easily be promoted to a method if need be.

I used to write Delphi code and you could declare a function within a function. Action and Func accomplish this same behavior for me in c#.

Here's a sample of repositioning controls with a delegate:

        private void Form1_Load(object sender, EventArgs e)
    {
        //adjust control positions without delegate
        int left = 24;

        label1.Left = left;
        left += label1.Width + 24;

        button1.Left = left;
        left += button1.Width + 24;

        checkBox1.Left = left;
        left += checkBox1.Width + 24;

        //adjust control positions with delegate. better
        left = 24;
        Action<Control> moveLeft = c => 
        {
            c.Left = left;
            left += c.Width + 24; 
        };
        moveLeft(label1);
        moveLeft(button1);
        moveLeft(checkBox1);
    }
Steve
nice example, thanks.
Edward Tanguay
+1 for the closure.
Joel Coehoorn
Interestingly, same number of lines
JustLoren
+10  A: 

They're also handy for refactoring switch statements.

Take the following (albeit simple) example:

public void Move(int distance, Direction direction)
{
    switch (direction)
    {
        case Direction.Up :
            Position.Y += distance;
            break;
        case Direction.Down:
            Position.Y -= distance;
            break;
        case Direction.Left:
            Position.X -= distance;
            break;
        case Direction.Right:
            Position.Y += distance;
            break;
    }
}

With an Action delegate, you can refactor it as follows:

static Something()
{
    _directionMap = new Dictionary<Direction, Action<Position, int>>
                        {
                            {Direction.Up, (p,d)=>p.Y+=d},
                            {Direction.Down, (p,d)=>p.Y-=d},
                            {Direction.Left, (p,d)=>p.X-=d},
                            {Direction.Right, (p,d)=>p.X-=d},
                        };
}

public void Move(int distance, Direction direction)
{
    _directionMap[direction](this.Position, distance);
}
Craig Vermeer
This is an incredibly useful technique for many reasons. Unlike switch statements, for instance, you can populate action maps dynamically from external data. Also, the key doesn't have to be an `int` or `string`.
Robert Rossney
This is powerful when needed, but remember that switch statements are often very fast, at least in implementations where jump tables can be used. I can't say whether or not .NET uses them or not.
Stuart Branham
A: 

I have a separate form that accepts a generic Func or an Action in the constructor as well as some text. It executes the Func/Action on a separate thread while displaying some text in the form and showing an animation.

It's in my personal Util library, and I use it whenever I want to do a medium length operation and block the UI in a non-intrusive way.

I considered putting a progress bar on the form as well, so that it could perform longer running operations but I haven't really needed it to yet.

SnOrfus
A: 

I use an Action to nicely encapsulate executing database operations in a transaction:

public class InTran
{
    protected virtual string ConnString
    {
        get { return ConfigurationManager.AppSettings["YourDBConnString"]; }
    }

    public void Exec(Action<DBTransaction> a)
    {
        using (var dbTran = new DBTransaction(ConnString))
        {
            try
            {
                a(dbTran);
                dbTran.Commit();
            }
            catch
            {
                dbTran.Rollback();
                throw;
            }
        }
    }
}

Now to execute in a transaction I simply do

new InTran().Exec(tran => ...some SQL operation...);

The InTran class can reside in a common library, reducing duplication and provides a singe location for future functionality adjustments.

Todd Stout
A: 

To get the propertyinfo of a specific property.

Jim G.
+2  A: 

Dunno if it's bad form to answer the same question twice or not, but to get some ideas for better uses of these types in general I suggest reading Jeremy Miller's MSDN article on Functional Programming:

Functional Programming for Everyday .NET Development

Craig Vermeer