C# 3.0 has many new features come from functional programming, which make C# 3.0 merging between imperative and functional language to be more powerful and elegant language.
The Functional Language consider as one of the most popular and the oldest programming paradigm [first functional language appears at 1955] has unique characteristics such as:
- The program considered as a set of functions.
- Functions do not change the program's status, all variables are immutable.
- No loops, recursion only :)
- and lambda expression.
For more information about FP => "Functional Programming on Wikipedia".
Lambda expression is unnamed function replaces anonymous method.
x => x * 2; //lambda expression
The previous statement means that x is a parameter of function, and x * 2 is the function body, we can rewrite this without lambda as the following:
int func(int x)
{
return x * 2;
}
lambda can accept more than one parameter using parentheses and commas
(x, y) => x * y ;
Can written as
int func (int x, int y)
{
return x * y;
}
To use lambda in useful way:
class Program
{
delegate int Increment2(int i); //delegate to call the function that created using lambda
static void Main(string[] args)
{
Increment2 I = x => x += 2; // assign lambda expression to delegate instance
Console.WriteLine(I(3)); // call it and return 5
}
Furthermore, to reduce the code amount we wrote, we can use the generic Func delegate.
Func delegate is a generic delegate to function can takes result type, and up to four parameters.
delegate TResult Func();
delegate TResult Func(T1 arg1);
delegate TResult Func(T1 arg1, T2 arg2);
delegate TResult Func(T1 arg1, T2 arg2, T3 arg3);
delegate TResult Func(T1 arg1, T2 arg2, T3 arg3, T4 arg4);
We can rewrite previous example using Func as the following:
Func<int, int> I = x => x += 2;
Note: the last generic parameter is the result type, and it’s mandatory.
Another generic delegate already exist is Action, Action is delegate to function that does not return a value.
e.g.
static void Main (string [] args)
{
var Persons = new List {
new Person{FirstName="First",lastName="Person"},
new Person{FirstName="Second",lastName="Person"},
new Person{FirstName="Third",lastName="Person"},
new Person{FirstName="Forth",lastName="Person"},
new Person{FirstName="Fifth",lastName="Person"},
};
Action print = person => Console.WriteLine(person);
Persons.ForEach(print);
}
On another side we can use lambda expression as parameter to another method.
List Names = new List();
Names.Add("Ahmad");
Names.Add("Mohammed");
Names.Add("Joseph");
Names.Add("Adam");
string findName = "Ahmad";
string name = Names.Find(str => str == findName); //use lambda as a parameter
if (string.IsNullOrEmpty(name))
Console.WriteLine("not found");
You can replace previous lambda with anonymous method
string name = Names.Find(delegate(string str) { return str == findName; });
You must notice from previous code that the lambda can access the outer variable
Now how can we use recursion using lambda:
To write recursion code, first we shall declare delegate using Func<> and assign it with null value, and assign instance delegate to lambda expression in new statement, we most write lambda recursion in two statement to avoid “Use of unassigned local variable” error.
e.g.
Func<int, int> factorial = null;
factorial = Num => Num == 1 ? Num : factorial(Num - 1);
lambda statement
lambda statement similar to lambda expression, but lambda statement use brackets because it‘s contains more than one statement, while lambda expression not.
Func<string, int, string> lstatement = (Name, Num) =>
{
string tempStr = null;
for (int i = 0; i <>
{
tempStr += Name;
}
return tempStr;
};
Console.WriteLine(lstatement("Omar",5));
Notes:
- Lambda expression can be converted to expression tree or to delegate.
- Lambda statement can convert only to delegate type.
- Anonymous methods must be explicitly typed their parameters, but lambda infers their types.