Delegate, Anonymous Method and Lamda Expression in C# (Part 2/2)
Anonymous methods are
similar to normal methods but they do not have a name and can be directly
assigned to a delegate. These methods are not reusable components that is why
they don’t have a method name. They make the code simple and more readable. One
reason why we need an anonymous method is that often times a method is created
so that it can be assigned to the delegate instance and called through the
delegate reference.
How to
create an anonymous method?
Anonymous methods are methods without a name which are
directly created and assigned to a delegate instance. See code below where displayTime is an instance of delegate Display that accepts no parameter and has
voice return type.
Display displayTime = delegate(){
Console.WriteLine(DateTime.Now.ToString("dd/mm/yyyy"));
};
delegate() means
that this anonymous method takes no parameter and {} defines the block of statements to be run when this anonymous
method is called via delegate’s instance. In this example we only have
console.write statement which prints the current date.
How does compiler know that the
anonymous method agrees with the method signature and return type specified by
the delegate? Well the compiler looks into delegate definition and compares the
parameter list and return type with that specified by the anonymous method. If
it has same parameter/s and return type as in definition of delegate, then the
anonymous method compiles successfully.
Example 1:
Anonymous method (no parameter & void return type)
The code below shows how to create an anonymous method that
can be assigned to delegate instance which accepts no argument/parameter and
whose return type is void.
using System;
namespace HelloWorld
{
public delegate void Display();
public class
Program
static void Main(string[] args)
{
Display displayTime = delegate (){
Console.WriteLine(DateTime.Now.ToString("dd/mm/yyyy"));
};
displayTime();
Console.ReadKey();
}
}
}
Here, first we created a
delegate named Display that can hold
reference to the method which takes no parameter and has a void return type.
Then in the main method, we created an instance of delegate named displayTime and assigned it an
anonymous method. Next we called the method referred by delegate instance that
is the anonymous method which shows the current date.
Example 2:
Anonymous method (two parameter & a return type)
using System;
namespace HelloWorld
{
public delegate string Print(string message, int noOfTimes);
class
Program
{
static void Main(string[] args)
{
Print printMessage = delegate(string s, int noOfTimes) {
string msg="";
for (int i = 0; i < noOfTimes;
i++)
{
msg += s + "\n";
}
return msg;
};
string text = printMessage("Write this five
times", 5);
Console.WriteLine(text);
Console.ReadKey();
}
}
}
Here we can see in the
above code that when we have parameter we simply write them within the enclosed
parenthesis of delegate (which in this case is delegate (string s, int noOfTimes) ) and after writing the method’s logic we end
it with a return statement (which in this case is return msg).
Outer Variable
in anonymous methods:
Just before closing this
topic, I want to discuss outer variable because then can cause trouble if
ignored. Outer variables are those variable whose scope (scope under which they
are declared) includes an anonymous method. When this happens, that variable is
accessible by the anonymous method and it does not go out of scope until the
delegate instance is collected by garbage collector. Let’s see an example of
outer variable.
using System;
namespace HelloWorld
{
public delegate void CountToFive();
class Program
{
public static CountToFive Method_Using_OV() {
int
countStart = 1;
//Captured Variable
CountToFive counting = delegate ()
{
int countEnd = countStart + 4;
for (countStart=1; countStart<=
countEnd; countStart++)
{
Console.WriteLine("Count = "+countStart +"\n");
}
};
return counting;
}
static void Main(string[] args)
{
CountToFive ov = Method_Using_OV();
ov();
Console.WriteLine( "Variable countStart
is captured by the anonymous method"
);
Console.WriteLine();
ov();
}
}
}
OUTPUT:
count = 1
count = 2
coutn = 3
count = 4
count = 5
Varuable countStart is captured by anonymous method
count = 1
count = 2
count = 3
count = 4
count = 5
count = 2
coutn = 3
count = 4
count = 5
Varuable countStart is captured by anonymous method
count = 1
count = 2
count = 3
count = 4
count = 5
In the example above, we
created a delegate that can refer to method which does not have a return type
and takes no argument. After that, we created a method which returns a delegate
instance which holds a reference to an anonymous method. The anonymous method
uses a local variable countStart
which is accessible through anonymous method as it is in its scope. This
variable is captured until the delegate instance is subject to garbage
collector.
After the first call to
the anonymous method from the delegate, the countStart value becomes 5. When the anonymous method is called
second time, countStart still exist
and value of it is still 5 which is assigned to countEnd and countEnd becomes 10. Similarly, if we
call it third time countEnd will
become 15 because countStart would
be 10 at that time.
Though the concept of captured variable looks strange at first but if you think of the logic behind it, then it would look obvious.
Lamda
Expression
The lamda expression is another handsome way of creating
anonymous function. Because of its shorthand approach to create an anonymous
method, it makes the program simple and easy to understand. The lamda
expression is mostly used with LINQ but it can also be used with delegates and
events.
The lamda expression
has a little different syntax. Let’s see an example
Example 1:
Lamda Expression for delegate referring to method with no parameter & void
return type
using System;
namespace HelloWorld
{
public delegate void DisplayHelloWorld();
{
static void Main(string[] args)
{
// Lamda Expression
DisplayHelloWorld disp = () => Console.WriteLine("Hello World!");
disp();
Console.ReadKey();
}
}
}
In the above code, see how delegate instance is given an
anonymous method through lamda expression. This is a shorthand as compare to
anonymous method. After the assignment operator = we have empty parenthesis ()
which shows that this delegate is referring to a method that does not take
any parameter. After that, we have =>
operator known as “becomes” after
this operator we define the body of the method which in this case is Console.WriteLine("Hello
World"); . Since it’s a single statement, we don’t need curly brackets
{}. If it were more than a single statement,
we would place curly brackets after =>
operator and it would be called Statement
Lamda rather than Lamda Expression.
So as you saw it is an easy way to create anonymous method.
Lets see another example, where the delegate requires method with some
parameter.
Example 2:
Lamda Expression for delegate referring to method with two parameters & a
return type
using System;
namespace HelloWorld
{
public delegate bool CompNo(decimal balance, decimal price);
class
Program
{
static void Main(string[] args)
{
CompNo canBuy = (b, p) => b - p
>= 0;
decimal balance = 10m, itemPrice=9m;
if (canBuy(balance,itemPrice))
Console.WriteLine("Yes, you have
sufficient balance to buy item.");
else
Console.WriteLine("You have insufficient
balance to buy item");
Console.ReadKey();
}
}
}
OUTPUT:
Yes, you have sufficient balance to buy item.
Yes, you have sufficient balance to buy item.
Well here the delegate CompNo
refers to method with two input parameter of type int and return a bool. The
lamda expression defines an anonymous method in which if the value of first parameter is greater than the second parameter then it returns true
else returns false. See how this function is so simply written and easy to
understand. You might be thinking that we did not specify the types of
parameter in lamda expression (b, p), well this is the beauty of
lamda expression that we don’t need to specify types in input parameters
because the compiler will do this for us by looking into the delegate
definition. We are also not required to write a return statement instead the
compiler understand that the expression is the actual value which is return.
Note: in lamda expression return
statement is not allowed. While in statement lamda return statement is allowed.
See example below.
Example 3:
Lamda Expression for delegate referring to method with two parameters & a
return type
using System;
namespace HelloWorld
{
public delegate int Cal (int x, int y);
class
Program
{
static void Main(string[] args)
{
Cal sum = (a,b) => a + b; //Lamda Expression
Cal sub = (a, b) => { return a - b; };//Statement Lamda
int x = sum(10, 10);
int y = sub (20, 9);
Console.WriteLine(x);
Console.WriteLine();
Console.WriteLine(y);
Console.ReadKey();
}
}
}
OUTPUT:
20
11
The example above declares a delegate named Cal that refers to a method whose return type is int and which accepts two int parameters. The instance sum of delegate Cal, assigns the delegate instance a method which computes the sum of input parameter using lamda expression. While another instance of delegate Cal, subtracts the second parameter from the first parameter using statement lamda.
20
11
The example above declares a delegate named Cal that refers to a method whose return type is int and which accepts two int parameters. The instance sum of delegate Cal, assigns the delegate instance a method which computes the sum of input parameter using lamda expression. While another instance of delegate Cal, subtracts the second parameter from the first parameter using statement lamda.
Comments
Post a Comment