There are remarkable changes in C# from Version 1.0. C# 2.0 and C# 3.0 has introduced lots of new things for the way we do the things. Here I would like to discuss about the use of Delegates and Lambda Expression's. Lambda Expressions has been introduced in C# 3.0 (2008).
What is Delegate?
"A delegate is a reference type that represents a method with a specific signature and return type."
Delegates allow you to pass a function to another function. As a concept, it's similar to functions as first-class types in functionally languages. A typical delegate usage is as a callback for asynchronous method calls.
A delegate in C# is similar to a function pointer in C or C++. Using a delegate allows the programmer to encapsulate a reference to a method inside a delegate object. The delegate object can then be passed to code which can call the referenced method, without having to know at compile time which method will be invoked.
Call a Function directly - No Delegate
In most cases, when we call a function, we specify the function to be called directly. If the class MyClass has a function named Process, we'd normally call it like this
(SimpleDelegateSample.cs):
namespace NoDelegate
{
public class MyClass
{
public void Invoke() {
Console.WriteLine("Invoke () begin");
Console.WriteLine("Invoke () end");
}
}
public class Test
{
static void Main(string[] args) {
MyClass myClass = new MyClass();
myClass.Invoke();
}
}
}
That works well in most situations. Sometimes, however, we don't want to call a function directly - we'd like to be able to pass it to somebody else so that they can call it. This is especially useful in an event-driven system such as a graphical user interface, when I want some code to be executed when the user clicks on a button, or when I want to log some information but can't specify how it is logged.
Call a Function - Delegate
namespace BasicDelegate
{
// Declaration
public delegate void SimpleDelegate();
class TestDelegate
{
public static void MyFunc() {
Console.WriteLine("I was called by delegate ...");
}
public static void Main() {
// Instantiation
SimpleDelegate simpleDelegate = new SimpleDelegate(MyFunc);
// Invocation
simpleDelegate();
}
}
}
A delegate can be initialized with inline code, called an "anonymous method." This method takes a string as an input parameter.
namespace ConsoleApplication1
{
class Program
{
delegate void Print(string s);
static void Main(string[] args) {
Print p = delegate(string s) { Console.WriteLine("We are printing" + s); };
p("Hello");
Console.Read();
}
}
}
What is Lambda Expression?
A lambda expression simply defines an anonymous function. A function is something that takes one or more parameters (just as a method does)
In C# 3, the "=>" syntax is used to write a lambda expression. You place the parameters to the left of the arrow and the expression to compute to the right. The lambda expression can be assigned to delegate as shown below
namespace ConsoleApplication1
{
class Program
{
delegate void Print(string s);
static void Main(string[] args) {
Print p = delegate(string s) { Console.WriteLine("We are printing" + s); };
p("Hello");
Console.WriteLine("Lambda Expression ");
Print p1 = (x) => { Console.WriteLine("We are printing using Lambda " + x); };
p1("Wow, it's Cool");
Console.Read();
}
}
}
Below is the Sample Code which shows use of delegate and lambda expression. I have take here the Type List so that I can show the different way of using "anonymous function"
Product.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ConsoleApplication
{
class Product
{
public string Name { get; private set; }
public decimal Price { get; private set; }
public Product(string name, decimal price)
{
Name = name;
Price = price;
}
public Product() { }
public static List<Product> GetProductInformation()
{
List<Product> prod = new List<Product>();
prod.Add(new Product("Soap", 11));
prod.Add(new Product("Toothpaste", 10));
prod.Add(new Product("Brush", 12));
prod.Add(new Product("Shampoo", 10));
return prod;
}
public override string ToString()
{
return string.Format("{0}: {1}", Name, Price);
}
}
}
Implemented the IComparer Interface to sort the product.
CompareProduct.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ConsoleApplication
{
class CompareProduct: IComparer<Product>
{
#region IComparer<Product> Members
public int Compare(Product x, Product y) {
return x.Name.CompareTo(y.Name);
}
#endregion
}
}
Main Program
Program.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ConsoleApplication
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Product .......");
foreach (Product pro in Product.GetProductInformation())
{
Console.WriteLine(pro.ToString());
}
Console.WriteLine(" Using IComparer Interface to Compare");
List<Product> product = Product.GetProductInformation();
product.Sort(new CompareProduct());
Console.WriteLine();
Console.WriteLine("Sorting 1.......");
foreach (Product pro in product)
{
Console.WriteLine(pro.ToString());
}
List<Product> product1 = Product.GetProductInformation();
Console.WriteLine();
Console.WriteLine("Sorting 2.......");
foreach (Product pro in product1.OrderBy(p => p.Name))
{
Console.WriteLine(pro.ToString());
}
List<Product> product2 = Product.GetProductInformation();
product2.Sort((first, second) => first.Name.CompareTo(second.Name));
Console.WriteLine();
Console.WriteLine("Sorting 3.......");
foreach (Product pro in product2)
{
Console.WriteLine(pro.ToString());
}
Predicate<Product> criteria = delegate(Product p)
{
return p.Price == 10;
};
List<Product> product3 = Product.GetProductInformation();
List<Product> matches = product3.FindAll(criteria);
Console.WriteLine("Finding with price 10.......");
Action<Product> print = delegate(Product p)
{
Console.WriteLine(p);
};
matches.ForEach(print);
Console.WriteLine("Lamda expression with Printing & Finding with price > 10.......");
List<Product> products = Product.GetProductInformation();
foreach (Product product4 in products.Where(p => p.Price > 10))
{
Console.WriteLine(product4);
}
Console.WriteLine("Delegate to Printing & Finding with price == 10.......");
List<Product> finalProduct = Product.GetProductInformation();
finalProduct.FindAll((delegate(Product p) { return p.Price == 10; })).ForEach((delegate(Product p) { Console.WriteLine(p); }));
Console.Read();
}
}
}