Knowledge is power. We love to share it.

News related to Mono products, services and latest developments in our community.

pajo

C# anonymous methods in action

04/02/2012

Anonymous methods / lambdas are a quite recent addition to the feature set of C#. For those of you working with dynamic languages like JavaScript, using anonymous functions will feel very natural. I’m working with a people who are using LINQ statements on a daily basis and who are very good at writing them, However, developer used to static languages, like myself, find it hard to use them outside of running LINQ queries. For those unfamiliar with anonymous methods or lambdas I suggest to take a look at this brief overview.

Recently I had a task where I needed to submit changes to three different services, and if any of them failed for any reason I had to restore all of them to their previous state. In essence, I needed to mimic transactional behavior. To make it a bit harder all of the services don’t need to be called in all scenarios - depending on the data submited they can be called in any combination. My first attempt included lots of housekeeping variables making it look ugly and hard to read. Additionally, I had to keep some of values that are specific to a single service visible throughout the scope of my method, something I like to avoid. What I really needed is a list of actions to run when I need to recover from an error. This is where anonymous methods step in. 

public void DoStuff()
{
    List<Action> rollbackActions = new List<Action>();
 
    try
    {
        if (shouldUpdateService1)
        {
            var service1 = Service1.GetInstance();
            var previousState = service1.GetObject();
            rollbackActions.Add(() =>
            {
                try
                {
                    service1.UpdateObject(previousState);
                }
                catch
                {
                    //notify rollback fail for this service
                }
            });
 
            service1.UpdateObject(newState);
        }
 
        if (shouldUpdateService2)
        {
            var service2 = Service2.GetInstance();
            var previousState = service2.GetObject();
            rollbackActions.Add(() =>
            {
                try
                {
                    service2.UpdateObject(previousState);
                }
                catch
                {
                    //notify rollback fail for this service
                }
            });
 
            service2.UpdateObject(newState);
        }
 
        if (shouldUpdateService3)
        {
            var service3 = Service3.GetInstance();
            var previousState = service3.GetObject();
            rollbackActions.Add(() =>
            {
                try
                {
                    service3.UpdateObject(previousState);
                }
                catch
                {
                    //notify rollback fail for this service
                }
            });
 
            service3.UpdateObject(newState);
        }
    }
    catch
    {
        rollbackActions.ForEach(p => p());
    }
}

As you can see code is very easy to read and maintain. All I needed is a list of actions to do if exception occurs. As you change state on every service you’re adding a rollback action, so there is no need to track state of what has been changed. All the code and objects specific to the single service can be kept inside it’s own if block making them visible only where they are needed - anonymous methods can reference outer objects even when they go out of scope.

You can also use methods that return values, and this can be useful when you have multi-criteria ranking like team table ranking. First criteria is the number of points teams have - if equal you should compare goal difference, after that you could compare who scored more goals and so on. You can compile your lists of actions to execute and run them when hey meet certain conditions, in this case you would have something like this 

public class Team : IComparable<Team>
{
    public string Name { get; set; }
    public int Points { get; set; }
    public int GoalsScored { get; set; }
    public int GoalsConceded { get; set; }
    public int GoalDiff { get { return this.GoalsScored - this.GoalsConceded; } }
 
    #region IComparable<Team> Members
 
    public int CompareTo(Team other)
    {
        int value = 0;
        IEnumerator<Func<int>> compareCriteria = new Func<int>[]
        {
            () => { return this.Points.CompareTo(other.Points); },
            () => { return this.GoalDiff.CompareTo(other.GoalDiff); },
            () => { return this.GoalsScored.CompareTo(other.GoalsScored); },
 
        }.ToList().GetEnumerator();
 
        while (compareCriteria.MoveNext() && value == 0)
        {
            value = compareCriteria.Current();
        }
 
        return value;
    }
 
    #endregion
}

The code is much more readable and easier to maintain when compared to the approach that uses nested if statements.  In this case our criteria list is static; if your list needs to be dynamic based on the state of two objects (for example in different leagues ranking rules can differ), the advantages of this technique are even grater. But you also need to be careful when using anonymous methods and understand how they work to avoid some of its pitfalls. As my colleague wrote in his blog, dynamically compiled code can have a serious performance hit on your code. All anonymous methods will be compiled at run-time which means executing them is way slower then calling any statically compiled method. In most cases this will be acceptable, but if you need to apply such techniques in very large and/or nested loops they can easily become performance bottlenecks. As always, this is not always the best approach, but it can certainly help in writing more robust and maintenable code.

Rated 4.44, 9 vote(s). 
By dd
absolutely great article on rollbacking using action delegates.
thanks - kesar