tags:

views:

501

answers:

8

Hello,

I've been seing Func<> for sometime now, and I've manage to avoid it (for now). But, now it looks like I can't dodge it forever. For instance, I tried Dynamic Linq, but almost everything was in terms of Func<>. I've tried one of my book (C# 2008/Deitel&Deitel) and also MSDN but I'm not getting it yet. They all jump straight in the subject.

  1. What can be said (in few words) about Func<>
  2. Can I get some links on the web that can get me started on that matter?

Thanks for helping

+3  A: 

You can start with 101 Linq Samples.

In short, Func<> is a delegate where the last type parameter is the return type.

So, Func<int,bool> is a delegate that takes an int parameter and returns a bool.

Oded
+12  A: 

Func<...> is a family of delegate types, that return some value, and take some number of arguments; for example:

  • Func<int,bool> is simply something that takes an int and returns a bool (the return is always at the end); for example a predicate:

    int[] data = {1,2,3,4,5};
    var odd = data.Where(i => i % 2 == 0);
    
  • Func<string> is a method that returns string, such as () => "hello world";.

  • Func<DateDtime, TimeSpan, DateTime> might be something like (when,howLong) => when + howLong;

Likewise there is Action<...> which does the same but without a return type.

There's nothing magic about Func<...> - it is just a simpler way of expressing delegates, while a: using generics (useful for LINQ), or b: not needing you to look up what the arguments are; if the delegate type is something obscure (PipeStreamImpersonationWorker for example) it can be hard to know what it takes; if that was expressed as the comparable Action it would be clear that it takes no parameters and returns void.

Marc Gravell
+1  A: 

Func<..., T> is delegate. where T is return-type, and all others - input parameters.

portland
+6  A: 

Func<int> (for example) is a type (in the way that string is a type). So you use it to declare variables, fields, parameters and so on.

It represents a computation that can be done whenever you ask it for an answer:

Func<int> f = () => DateTime.Now.Second;

// elsewhere...

Console.WriteLine( f() );

Note how you can call it just like a method. There are many overloaded versions of Func to support different numbers of parameters. The last type argument is the return type.

Func<int, string> quoteInt = n => "\"" + n + "\"";

Console.WriteLine( quoteInt(3) );

Func is a delegate type. You can declare your own, but it's easier to use Func. Where you want to return void, use Action instead of Func. You only need to declare custom delegates if you need out or ref parameters.

When assigning a lambda to a Func, you can refer to local variables. This is extremely powerful; it means that a Func is more than just code; it has data. So it's like an object with a single method (which technically it is - the method is called Invoke and the compiler implicitly calls that method for you when you call a delegate).

The syntax () => can be placed before any expression to say "don't do this now, delay it until later". It allows you to initialize a delegate capturing the delayed computation. And then the syntax () can be placed after the delegate to actually trigger the computation. So suffix () is kind-of the opposite of prefix () =>.

Daniel Earwicker
+1 for a neat explanation.
KMan
+26  A: 

Func<> is a generic delegate - it is just very convenient to use, because you don't have to create your own delegate for each argument/return type combination.
Earlier, you had to write something like:

public delegate long MyDelegate( int number );

public void Method( IEnumerable<int> list, MyDelegate myDelegate )
{
    foreach( var number in list )
    {
        myDelegate( number );
    }
}

You had to publish your delegate so that a user can call your method correctly. Especially when you need a bunch of different delegates you ended up publishing one for every argument list and return type.
With Func<> you just write:

public void Method( IEnumerable<int> list, Func<int, long> myDelegate )
{
    foreach( var number in list )
    {
        myDelegate( number );
    }
}

It means the same as the first code example - Func<int, long> defines a delegate that takes one integer argument and returns a long value.

Of course you can use longer parameter lists, too: Func<int, int, bool, long> will still return a long value while it takes two ints and a bool value. If you wish a delegate without return value you will have to use Action<>, which will have void as a return type.

EDIT (by request): How to call the method in my example:

For the caller, there is no difference between the solution with MyDelegate or Func<>. In both cases he has three options to call the method:

Using a lambda notation (C# 3.0 required, probably the best solution for short methods):

Method( myList, i => i * i );

By using an anonymous method (C# 2.0 required):

Method( myList, delegate( int i )
{
    return i * i;
} );

Or by using a real method as an argument:

Method( myList, Square );

private static long Square( int number )
{
    return number * number;
}
tanascius
Very nice explination!
John
Good explanation. Would be good to include an example of using/calling the Method as well.
Metro Smurf
@Metro: I added some examples how to call the method
tanascius
very nice, +1 for this
Michel
+9  A: 

This might help. Suppose every time you see Func<int, string> you think to yourself:

interface IFuncIntString
{
    string Invoke(int x);
}

That is, the delegate is an object that implements this interface. It has a single method called Invoke which takes an int and returns a string.

Now add to that the feature that you can omit the "Invoke" on a call, and you've got yourself a delegate.

Eric Lippert
That's how I like to think of delegates.
kenny
Best way to explain it to a Java programmer ;)
juharr
+1  A: 

If you've ever used the => operator in c#, and you probably have, you've already used Funcs. You just haven't been explicitly declaring them.

So, if you write a statement like

var peopleWhoLikeBlue = people.Where(person => person.FavoriteColor == "Blue");

you're passing a Func<Person, bool> into the Where() method.

If you want to be wordy, you can rewrite that statement like this:

Func<Person, bool> favoriteColorIsBlue = person => person.FavoriteColor == "Blue";
var peopleWhoLikeBlue = people.Where(favoriteColorIsBlue);

And you'll get the same result.

Jeremy Frey