C# - Func
We have learned in the previous section, that a delegates can be defined as shown below.
Example: C# Delegate
public delegate int SomeOperation(int i, int j);
class Program
{
static int Sum(int x, int y)
{
return x + y;
}
static void Main(string[] args)
{
SomeOperation add = Sum;
int result = add(10, 10);
Console.WriteLine(result);
}
}
Output:
20
C# 3.0 includes built-in generic delegate types
Func
and Action
, so that you don't need to define custom delegates as above.
Func is a generic delegate included in the
System
namespace. It has zero or more inputparameters and one out parameter. The last parameter is considered as an out parameter.
For example, a Func delegate that takes one input parameter and one out parameter is defined in the System namespace as below:
Signature: Func
namespace System
{
public delegate TResult Func<in T, out TResult>(T arg);
}
The last parameter in the angle brackets <> is considered as the return type and remaining parameters are considered as input parameter types as shown in the following figure.
A Func delegate with two input parameters and one out parameters will be represent as below.
The following
Func
type delegate is the same as the above SomeOperation
delegate, where it takes two input parameters of int type and returns a value of int type:Func<int, int, int> sum;
You can assign any method to the above func delegate that takes two int parameters and returns an int value. Now, you can take Func delegate instead of someOperation delegate in the first example.
Example: Func
class Program
{
static int Sum(int x, int y)
{
return x + y;
}
static void Main(string[] args)
{
Func<int,int, int> add = Sum;
int result = add(10, 10);
Console.WriteLine(result);
}
}
Output:
20
A Func delegate type can include 0 to 16 input parameters of different types. However, it must include one out parameter for result. For example, the following func delegate doesn't have any input parameter, it includes only a out parameter.
Example: Func with Zero Input Parameter
Func<int> getRandomNumber;
C# Func with an Anonymous Method
You can assign an anonymous method to the Func delegate by using the delegate keyword.
Example: Func with Anonymous Method
Func<int> getRandomNumber = delegate()
{
Random rnd = new Random();
return rnd.Next(1, 100);
};
Func with Lambda Expression
A Func delegate can also be used with a lambda expression, as shown below:
Example: Func with lambda expression
Func<int> getRandomNumber = () => new Random().Next(1, 100);
//Or
Func<int, int, int> Sum = (x, y) => x + y;
Points to Remember :
- Func is built-in delegate type.
- Func delegate type must return a value.
- Func delegate type can have zero to 16 input parameters.
- Func delegate does not allow ref and out parameters.
- Func delegate type can be used with an anonymous method or lambda expression.
Why would you use Expression<Func<T>> rather than Func<T>?
I understand lambdas and the
Func
and Action
delegates. But expressions stump me. In what circumstances would you use an Expression<Func<T>>
rather than a plain old Func<T>
?
When you want to treat lambda expressions as expression trees and look inside them instead of executing them. For example, LINQ to SQL gets the expression and converts it to the equivalent SQL statement and submits it to server (rather than executing the lambda).
Conceptually,
Expression<Func<T>>
is completely different from Func<T>
. Func<T>
denotes a delegate
which is pretty much a pointer to a method and Expression<Func<T>>
denotes a tree data structure for a lambda expression. This tree structure describes what a lambda expression does rather than doing the actual thing. It basically holds data about the composition of expressions, variables, method calls, ... (for example it holds information such as this lambda is some constant + some parameter). You can use this description to convert it to an actual method (with Expression.Compile
) or do other stuff (like the LINQ to SQL example) with it. The act of treating lambdas as anonymous methods and expression trees is purely a compile time thing.Func<int> myFunc = () => 10; // similar to: int myAnonMethod() { return 10; }
will effectively compile to an IL method that gets nothing and returns 10.
Expression<Func<int>> myExpression = () => 10;
will be converted to a data structure that describes an expression that gets no parameters and returns the value 10:
While they both look the same at compile time, what the compiler generates is totally different.
No comments:
Post a Comment