Blue Theme Orange Theme Green Theme Red Theme
 
Click Here for 3 Month Free of ASP.NET Hosting!
Home | Forums | Videos | Photos | Downloads | Blogs | E-Books | Interviews | Jobs | Beginners | Training
 | Consulting  
Submit an Article Submit a Blog 
 Login Close
User Id:
Password:
 
Forgot Password
Forgot Username
Why Register
 Jump to
Skip Navigation Links
TechnologyExpand Technology
WebsiteExpand Website
Dundas Dashboard
 Resources  
Close
 Our Network  
Close
Search :       Advanced Search »
Home » C# Language » Methods, Delegates, Anonymous Delegates, and Lambda Expressions... Oh My!

Methods, Delegates, Anonymous Delegates, and Lambda Expressions... Oh My!

This article covers different syntax we can use for declaring and executing methods.

Author Rank:
Technologies: .NET 1.0/1.1,Visual C# .NET
Total downloads : 146
Total page views :  10843
Rating :
 5/5
This article has been rated :  2 times
   Print Read/Post comments Post a comment  Rate  
   Email to a friend  Bookmark  Similar Articles  Author's other articles  
Download Files:
LambdaSample.zip
 
Become a Sponsor


Related EbooksTop Videos

What Everyone Already Knows....

If we have a method declared as follows:

static Int32 SomeMethod(Int32 input)
{
    return input + 1;
}

We can explicitly call it in a way every C# programmer should be familiar with:

Int32 y = SomeMethod(5);
Console.WriteLine(y);

Using a Delegate...

Now, we may want to wrap this call so we can execute it from somewhere else.  This is done through a delegate. 

What's a delegate?

A delegate is an object instance  that "wraps" a method call (pretty much everything in the .NET framework in an object).  An easy way to think of it is as a reference to a method that we can pass around separately from the object that "ownes" the method.  In order to "wrap" the method call, the delegate needs two things:

  1. A reference to the instance of the object it will be calling the method on.
    and
  2. A reference to the method.

To create a delegate we first declare our delegate type.  We can think of this as being similar to declaring a new class:

delegate Int32 SomeMethodDelegate(Int32 input);

And then we can use an instance of this delegate to "wrap" our method call:

Using the same method we had earlier...

static Int32 SomeMethod(Int32 input)
{
    return input + 1;
}

Somewhere else in our code we can instantiate the delegate as follows.  (note: in the sample below, "Program" is a static class)

// f is a delegate object that "wraps" the call
SomeMethodDelegate f = new SomeMethodDelegate(Program.SomeMethod);

Now we can use our delegate instance to call the same method.

Int32 y = f(5);

The compiler is smart enough to figure out which kind of delegate to instantiate  so we can use a shorter syntax if we want. We are actually still very explicitly instantiating a delegate by telling the compiler what kind of delegate we want with the declaration on the left hand side of the assignment operator. (note: I don't need to specify the object in the following code sample because the delegate instantiation is in the same class as "SomeMethod()".)

// f is a delegate object that "wraps" the call
SomeMethodDelegate f = SomeMethod;

Adding Generics in the Mix....

We may not need a bunch of explicit delegate types lying around in our project (although sometimes it is good to have a few for more readable code) and can use generics to consolidate all delegates with similar surface areas (the same input and output types):

delegate TOutput GenericDelegate<TInput, TOutput>(TInput input);

Now we can wrap our method using our generic delegate just as before:

// using generic delegate definition
GenericDelegate<Int32, Int32> f = SomeMethod;
Int32 y = f(5);

Note: this GenericDelegate<>  is the same as the Func<> delegate defined in the 3.0 framework

// using built-in Func<> generic delegate definition (3.0 framework)
Func<Int32, Int32> f = SomeMethod;
Int32 y = f(5);

We also have the generic Action<> delegate which wraps a method with no return value and a Predicate<> delegate which is usually used to perform tests returns a Boolean and a Comparison<> delegate to compare two objects.

Anonymous Delegate....

We may want to have a method that does not belong to a class (which is why we call it anonymous) and can declare it in-line using  the following syntax.  Notice how the method has no "outer shell" definition.  The "SomeMethodDelegate" object is still instantiated and points to the in-line method.

// in-line method definition... it has no name so it is anonymous
SomeMethodDelegate f = delegate(Int32 x) { return x + 1; };
Int32 y = f(5);

We could use the same syntax to instantiate our anonymous delegate as well

// in-line method definition... it has no name so it is anonymous
Func<Int32, Int32> f = delegate(Int32 x) { return x + 1; };
Int32 y = f(5);

If you haven't done it already, it is worth taking some time and using the debugger to step through code containing anonymous method to get a better understanding of how the execution of the code flows.

Closures...

One of the ultra-cool features of anonymous methods is that they support closures which is a concept coming out of functional programming languages.  Closures are VERY powerful and can help us keep code more concise.  When a language supports closures it basically  means that the a method body has access to any local variable declared outside it's scope.

String hi = "Hello World";
Action<String> myAction = Console.WriteLine;
Func<String> myStringGetter = delegate()
{
    // the variable "hi" is available here because
    // anonymous methods support closure
    return hi;
};

myAction(myStringGetter());

Lambda Expressions...

The syntax for declaring an anonymous delegate is pretty verbose (and kind of ugly).  With the 3.5 Framework, we have a much shorter (and nicer) way to instantiate anonymous delegates using lambda expressions.

SomeMethodDelegate f = x => { return x + 1;  };
Int32 y = f(5);

The input parameter is the variable before the => symbol.

x => { return x + 1;  };

The body of the method is what appear after the => symbol.

x => { return x + 1;  };

Because the "SomeMethodDelegate" signature says we have to input a Int32 and output an Int32, the compiler knows that our "x" variable should be an integer (see if makes more sense if you try and match the delegate signature (below) up with our lambda expression (above). 

delegate Int32 SomeMethodDelegate(Int32 input);

We can use an even shorter syntax for declaring simple anonymous methods with the lamba expression and leave off the brackets and the "return" keyword.  The following code uses the simpler syntax:

// can use shorter syntax if you don't want brackets or "return" keyword
SomeMethodDelegate f = x => x + 1;
Int32 y = f(5);
Console.WriteLine(y);

Of course we can use lambda expressions with generic delegates as well.  The following shows the lambda expression syntax  for instantiating a generic delegate with two input parameters.  If our delegate has multiple input parameters, we must group them in parenthesis:

Func<Int32, Int32, Int32> add = (m, n) => m + n;
Int32 y = add(3, 4);

What Are They Good For?

Delegates are used most frequently for subscribing to events so we'll look at how we can utilize delegates with an object that exposes an event.

Here is our dummy event raising object which could just as easily be a UI form or control.

class Broadcast
{
    private event EventHandler m_somethingHappened;
    public event EventHandler SomethingHappened
    {
        add { m_somethingHappened += value; }
        remove { m_somethingHappened -= value; }
    }

    public void Fire()
    {
        if (null != m_somethingHappened)
            m_somethingHappened(this, EventArgs.Empty);
    }
}

Example 1:

Let's say we instantiate a new Broadcast object and want to wire up the events using anonymous delegates:

Broadcast bc = new Broadcast();

bc.SomethingHappened += delegate(Object sender, EventArgs args)
{
        Console.WriteLine("Something Happened (anonymous method)");
};

bc.Fire();

Example 2:

We can also wire up our Broadcast object using a lambda expression:

Broadcast bc = new Broadcast();
bc.SomethingHappened += (snd, arg) => Console.WriteLine("Something Happened (Lambda)");
bc.Fire();

Example 3:

There are also many other places where delegates can be useful.  Another scenario is when we need to pass a delegate to another method for execution. See if you can figure out what's happening in the following code. 

If we have a method declared that accepts a delegate and another item defined as its input parameters, it will execute the method using the second parameter as input.

static TOutput ExecuteSomething<TInput, TOutput>(Func<TInput, TOutput> mthd, TInput input)
{
    return mthd(input);
}

Can you figure out what will happen with the following call to our method?

Console.WriteLine(ExecuteSomething(g => g - 5, 20));

Example 4:

Many of the methods off of the List<> object take delegates as arguments.

namespace System.Collections.Generic
{
    public class List<T>     {
        public List<TOutput> ConvertAll<TOutput>(Converter<T, TOutput> converter);
        public bool Exists(Predicate<T> match);
        public T Find(Predicate<T> match);
        public List<T> FindAll(Predicate<T> match);
        public int FindIndex(Predicate<T> match);
        public int FindIndex(int startIndex, Predicate<T> match);
        public int FindIndex(int startIndex, int count, Predicate<T> match);
        public T FindLast(Predicate<T> match);
        public int FindLastIndex(Predicate<T> match);
        public int FindLastIndex(int startIndex, Predicate<T> match);
        public int FindLastIndex(int startIndex, int count, Predicate<T>
        public void ForEach(Action<T> action);
        public int RemoveAll(Predicate<T> match);
        public void Sort(Comparison<T> comparison);
        public bool TrueForAll(Predicate<T> match);
    }
}

As an example, let's use the FindAll() method to filter a list of integers using an anonymous delegate written in lambda syntax:

Random r = new Random();
List<Int32> myList = new List<int>();

// fill the list with random integers
for (int i = 0; i < 1000; i++)
    myList.Add(r.Next());

// filter the list using a delegate
List<Int32> myFilteredList = myList.FindAll(x => x < Int32.MaxValue/4);

Well, that's about it for the ways we have to call methods and some of the uses of delegates.  I hope you enjoyed the tour.

Until Next Time,
Happy coding


Login to add your contents and source code to this article
 [Top] Rate this article
 About the author
 
Matthew Cochran
Looking for C# Consulting?
C# Consulting is founded in 2002 by the founders of C# Corner. Unlike a traditional consulting company, our consultants are well-known experts in .NET and many of them are MVPs, authors, and trainers. We specialize in Microsoft .NET development and utilize Agile Development and Extreme Programming practices to provide fast pace quick turnaround results. Our software development model is a mix of Agile Development, traditional SDLC, and Waterfall models.
Click here to learn more about C# Consulting.
 
Introducing MaxV - one click. infinite control. Hyper-V Hosting from MaximumASP.
Finally – a virtual platform that delivers next-generation Windows Server 2008 Hyper-V virtualization technology from a managed hosting partner you can truly depend on. Visit www.maximumasp.com/max for a FREE 30 day trial. Hurry offer ends soon. Climb aboard the MaxV platform and take advantage of High Availability, Intelligent Monitoring, Recurrent Backups, and Scalability – with no hassle or hidden fees. As a managed hosting partner focused solely on Microsoft technologies since 2000, MaximumASP is uniquely qualified to provide the superior support that our business is built on. Unparalleled expertise with Microsoft technologies lead to working directly with Microsoft as first to offer IIS 7 and SQL 2008 betas in a hosted environment; partnering in the Go Live Program for Hyper-V; and product co-launches built on WS 2008 with Hyper-V technology.
Dynamic PDF
ceTE software specializes in components for dynamic PDF generation and manipulation. The DynamicPDF™ product line allows you to dynamically generate PDF documents, merge PDF documents and new content to existing PDF documents from within your applications.
Go.NET
Build custom interactive diagrams, network, workflow editors, flowcharts, or software design tools. Includes many predefined kinds of nodes, links, and basic shapes. Supports layers, scrolling, zooming, selection, drag-and-drop, clipboard, in-place editing, tooltips, grids, printing, overview window, palette. 100% implemented in C# as a managed .NET Control. Document/View/Tool architecture with many properties&events. Optional automatic layout.
Dundas Software
Dundas Chart for .NET is the most advanced .NET charting package available today.  With an extremely complete feature set, elegant architecture and easy implementation, Dundas Chart can quickly add advanced Charting functionality to enhance and transform ASP.NET and Windows Forms applications.  Whether you are implementing charting into internal projects, or building applications for clients, Dundas Chart offers advanced technology and advanced results to get the most out of data.
Clickatell's SMS Gateway
Clickatell's Developer Solutions allow you to SMS enable any website or application via a range of API's. Learn More about our API connections.
Free access to .NET Memory Management video
Everything you need to know about Garbage Collection, Temporary Objects, Fragmentation, Finalization and common causes of memory leaks in .NET. Watch the video here.
Microsoft Visual Studio 2010
Microsoft Visual Studio 2010 offers more to developers than any other Visual Studio release. Work more productively and collaboratively-with greater control over your work at every step. The Beta 2 can give you a head start on achieving efficiency.
 
   Print Read/Post comments Post a comment  Rate  
   Email to a friend  Bookmark  Similar Articles  Author's other articles  
Download Files:
LambdaSample.zip
 
 Post a Feedback, Comment, or Question about this article
Subject:  
Comment:  
Dundas Dashboard
Become a Sponsor
 Comments
Great work by Erik On March 23, 2008
Hi Matthew, I just want to let you know that I really do appreciate your posts, they are absolutely great!
Reply | Email | Delete | Modify | 
Great Walkthrough of the Various Breeds of Delegates by Mike On March 24, 2008
Nice explanation, Matt. I learned a few good things here about some of the nuances of anonymous delegates.
Reply | Email | Delete | Modify | 
Nice work Must Read.... by Pramod On September 11, 2009
This session is interesting and knowledgeable for all those who are confused with Delegates, Anonymous Delegates, and Lambda Expressions.

This is a must read article...I really appreciate one..
Reply | Email | Delete | Modify | 

 Hosted by MaximumASP  |  Found a broken link?  |  Contact Us  |  Terms & conditions  |  Privacy Policy  |  Site Map  |  Suggest an Idea  |  Media Kit
Current Version: 5.2009.6.2
 © 1999 - 2009  Mindcracker LLC. All Rights Reserved