问题
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.
- What can be said (in few words) about Func<>
- Can I get some links on the web that can get me started on that matter?
Thanks for helping
回答1:
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;
}
回答2:
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
.
回答3:
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.
回答4:
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 () =>
.
回答5:
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
.
回答6:
Func<..., T> is delegate. where T is return-type, and all others - input parameters.
回答7:
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.
来源:https://stackoverflow.com/questions/2661669/in-few-words-what-can-be-said-about-func