views:

73

answers:

2

I've downloaded the VCSharpSample pack from Microsoft and started reading on Anonymous Delegates. I can more or less understand what the code is doing, but I don't understand the reason behind it. Maybe if you gave me some examples where it would result in cleaner code and easier maintainability then I could wrap my head around it. :)

Can you help?

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ConsoleApplication2
{
    delegate decimal CalculateBonus(decimal sales);

    class Player
    {
        public string Name;
        public decimal Score;
        public decimal Bonus;
        public CalculateBonus calculation_algorithm;
    }

    class Program
    {        
        static decimal calculateStandardBonus(decimal sales)
        {
            return sales / 10;
        }

        static void Main(string[] args)
        {
            decimal multiplier = 2;

            CalculateBonus standard_bonus = new CalculateBonus(calculateStandardBonus);
            CalculateBonus enhanced_bonus = delegate(decimal sales) { return multiplier * sales / 10; };

            Player[] players = new Player[5];

            for (int i = 0; i < 5; i++)
            {
                players[i] = new Player();
            }

            players[0].Name = "Sergio";
            players[0].Score = 240;
            players[0].calculation_algorithm = standard_bonus;

            players[1].Name = "Sergio";
            players[1].Score = 240;
            players[1].calculation_algorithm = enhanced_bonus;

            players[2].Name = "Caro";
            players[2].Score = 89;
            players[2].calculation_algorithm = standard_bonus;

            players[3].Name = "Andy";
            players[3].Score = 38;
            players[3].calculation_algorithm = enhanced_bonus;

            players[4].Name = "Hugo";
            players[4].Score = 600;
            players[4].calculation_algorithm = enhanced_bonus;

            foreach (Player player in players)
            {
                PerformCalculationBonus(player);
            }

            foreach (Player player in players)
            {
                DisplayPersonalDetails(player);
            }

            Console.ReadLine();
        }

        public static void PerformCalculationBonus(Player player)
        {
            player.Bonus = player.calculation_algorithm(player.Score);
        }

        public static void DisplayPersonalDetails(Player player)
        {
            Console.WriteLine(player.Name);
            Console.WriteLine(player.Score);
            Console.WriteLine(player.Bonus);
            Console.WriteLine("---------------");
        }
    }
}
+1  A: 

The benefit is that you don't have to look somewhere else for the code to do a one-time lookup/change/calculation/whatever. It's a bit annoying to have to add a function (or a whole other class for a function!) you'll only ever use in one place, and then you have to look back later and see what that bit of code was and why it's needed and whether it still is.

With an anonymous delegate, the code is right there in the code that uses it.

cHao
Aha! Now I can see its use for this particular example I posted in the question. But wouldn't this only be useful if the method in question only had a single line of code?
Sergio Tapia
Possibly. It's best for very small one-off functions. If your anonymous function is too big, it also increases the size of its containing function -- and keeping functions small (which is generally a good idea) would mean breaking that code out into a real function and using it by name. (If a function is that big, hopefully you'd be able to use it elsewhere anyway.)
cHao
+6  A: 

Anonymous delegates are designed to help you make code more readable by being able to define the behavior of a simple delegate inline in another method. This means that if you're dealing with something that requires a delegate (an event handler, for example), you can define the behavior right in the code rather than creating a dedicated function for it.

In addition, they're the precursor for lambda expressions. Things like LINQ to Objects (any of the methods that operate on IEnumerable<T>) use delegates to perform queries on objects. For example, if you have a collection of strings and you want a query that finds all of them that are five characters long, you can do that with a lambda:

List<string> strings = ...

var query = strings.Where(s => s.Length == 5);

Or you could do it with an anonymous delegate:

var query = strings.Where(delegate(string s) { return s.Length == 5; });

If you didn't have these, your code would look something like this:

var query = strings.Where(IsFiveCharacters);

...

private bool IsFiveCharacters(string input)
{
    return input.Length == 5;
}

It's important to realize, though, that lambdas and anonymous delegates are just compiler features. When your code is compiled, it does actually create regular functions like in the last example, but they're hidden and named using characters that are illegal in the language being used. There's a lot of logic that goes around them when doing things like closures (where you access a variable that exists outside of the lambda/anonymous delegate declaration), as well.

Adam Robinson
+1: Very nice..
Robert Harvey
+1 Love your lambda example. Broke it down very nice. Do you think you can break it down similar for an event?
jsmith
So they are basically only useful if you are creating a method that only has one line of code to it? To avoid going to see what it does every time?
Sergio Tapia
Both lambda and anon delegates can contain multiple lines of code. They are useful in writing code where that code is used rather than spread out. Should you write lambda or anon delegate that has many lines of code? That's for you to decide. It's your code, your organization scheme.
Tergiver
@Sergio: As @Tergiver points out, they can be multiline (in C#, not in VB.NET prior to VS2010), but long and complex lambdas are generally better suited as functions, rather than cluttering up their defining method.
Adam Robinson
@jsmith: I'm not sure what you mean; what exactly are you looking for as far as events go, or are you looking for an events example using lambdas?
Adam Robinson
@Adam Sorry for not clarifying. I was hoping for a break down of how to create/use an event with an anonymous delegate. Specifically how the compiler breaks it down. I'm sure it's very similar.
jsmith
@jsmith: It's exactly the same. The usage of the anonymous delegate or lambda doesn't have any impact on how the compiler generates the underlying code.
Adam Robinson