Wintellect  

Browse by Tags

All Tags » delegates   (RSS)

What is the relationship between lambda expressions, anonymous methods, and delegates? The answer is, in two words: syntactic sugar ... or is it?

To show this, I put together a real simple console program that declares a delegate which returns a string. I then declare a concrete method that matches the delegate signature, and another method that takes the delegate and writes the return value to the console. I then call it with the concrete instance, an anonymous method, and a lambda expression. The code looks like this (just go into VisualStudio and start a new C# console project, then paste this over everything and run it):

using System;

namespace SyntacticSugar
{
    /// <summary>
    ///     Main program
    /// </summary>
    class Program
    {
        /// <summary>
        ///     Delegate that returns a string
        /// </summary>
        /// <returns>The string</returns>
        private delegate string WriteSomething();       

        /// <summary>
        ///     Concrete implementation of the delegate
        /// </summary>
        private static string _Concrete()
        {
            return "Concrete method";
        }

        /// <summary>
        ///     Main method
        /// </summary>
        static void Main()
        {
            // call using a concrete method
            _DoWrite(_Concrete);

            // call using an anonmymous method
            _DoWrite(delegate() { return "Anonymous method"; });

            // call using lambda expression
            _DoWrite(()=>"Lambda BLOCKED EXPRESSION;

            Console.ReadLine();
        }

        /// <summary>
        ///     Takes the delegate and writes the string to the console
        /// </summary>
        /// <param name="something">The string to write</param>
        private static void _DoWrite(WriteSomething something)
        {
            Console.WriteLine(something());
        }
    }
}

When you call the program, you get what we expect: three lines of text, concrete, the anonymous, then lambda. That's all great, but what happens under the covers? Again, we'll go to ildasm.exe to pick apart the code that was generated.

The first thing of note is that the compiler generated two delegates for us, one is highlighted below ... also note the <Main>b__ methods generated for the expressions:

Syntactic Sugar Example

What's even more interesting is when we look at the IL generated for the methods. I have put them together here for easy reference ... you can tell which is the concrete class, anonymous method, and lambda expression by the string literal:

  IL_0001:  ldstr      "Concrete method"
  IL_0006:  stloc.0
  IL_0007:  br.s       IL_0009
  IL_0009:  ldloc.0
  IL_000a:  ret
...
  IL_0001:  ldstr      "Anonymous method"
  IL_0006:  stloc.0
  IL_0007:  br.s       IL_0009
  IL_0009:  ldloc.0
  IL_000a:  ret
...
  IL_0000:  ldstr      "Lambda expression"
  IL_0005:  stloc.0
  IL_0006:  br.s       IL_0008
  IL_0008:  ldloc.0
  IL_0009:  ret

It's interesting to note that, other than the screen literal (and a "nop" at the top of the anonymous method), the code is exactly the same in each case.

Next, let's dig into the actual calls from the Main method ... I've truncated the code to focus on the important pieces:

// load a pointer to the method, note the pointer "points to" _Concrete
  IL_0002:  ldftn      string SyntacticSugar.Program::_Concrete()
  IL_0008:  newobj     instance void SyntacticSugar.Program/WriteSomething::.ctor(object,
                                                                                  native int)
  IL_000d:  call       void SyntacticSugar.Program::_DoWrite(class SyntacticSugar.Program/WriteSomething)
// now we're a little more involved ... note the "difference" between
// the anonymous method and the lambda expression ... none! 
// 
// anonymous:
  IL_0013:  ldsfld     class SyntacticSugar.Program/WriteSomething SyntacticSugar.Program::'CS$<>9__CachedAnonymousMethodDelegate2'
  IL_0018:  brtrue.s   IL_002d
  IL_001a:  ldnull
  IL_001b:  ldftn      string SyntacticSugar.Program::'b__0'()
  IL_0021:  newobj     instance void SyntacticSugar.Program/WriteSomething::.ctor(object,
                                                                                  native int)
  IL_0026:  stsfld     class SyntacticSugar.Program/WriteSomething SyntacticSugar.Program::'CS$<>9__CachedAnonymousMethodDelegate2'
  IL_002b:  br.s       IL_002d
  IL_002d:  ldsfld     class SyntacticSugar.Program/WriteSomething SyntacticSugar.Program::'CS$<>9__CachedAnonymousMethodDelegate2'
  IL_0032:  call       void SyntacticSugar.Program::_DoWrite(class SyntacticSugar.Program/WriteSomething)
  IL_0037:  nop

// now the lambda ... deja vu?
  IL_0038:  ldsfld     class SyntacticSugar.Program/WriteSomething SyntacticSugar.Program::'CS$<>9__CachedAnonymousMethodDelegate3'
  IL_003d:  brtrue.s   IL_0052
  IL_003f:  ldnull
  IL_0040:  ldftn      string SyntacticSugar.Program::'b__1'()
  IL_0046:  newobj     instance void SyntacticSugar.Program/WriteSomething::.ctor(object,
                                                                                  native int)
  IL_004b:  stsfld     class SyntacticSugar.Program/WriteSomething SyntacticSugar.Program::'CS$<>9__CachedAnonymousMethodDelegate3'
  IL_0050:  br.s       IL_0052
  IL_0052:  ldsfld     class SyntacticSugar.Program/WriteSomething SyntacticSugar.Program::'CS$<>9__CachedAnonymousMethodDelegate3'
  IL_0057:  call       void SyntacticSugar.Program::_DoWrite(class SyntacticSugar.Program/WriteSomething)

As you can see, all of these methods (pardon the pun) use delegates and method pointers, but when it comes to lambda expressions, you're really just using what some consider to be a more elegant way of generating an anonymous method, which in turn is really the "value" of the delegate "variable."

But wait! There's more ...

So this example is compelling, but according to Eric Lippert in his blog post, there is more than just syntactic sugar taking place. Here is the important bit:

The problem is that since we do not know the types of the parameters until the target type is determined, it means that we cannot aggressively bind (by "bind" I mean "do full semantic analysis") the body of the lambda when the binder encounters the lambda. Rather, we have to put the lambda aside and say "come back to this thing later when we know what the target type is". In C# 2.0 anonymous method bodies were bound eagerly because we always had enough information to determine if there was an error inside the anonymous method even if we didn't know the target type. We could bind the body first, and then later on double-check during convertibility checking to make sure that the parameter types and return type were compatible with the delegate. Every expression type in the compiler worked this way: you do a full analysis of the expression, and then you see if it is compatible with the type that it is being converted to. With lambdas, the information flows in the opposite direction through the binder; first we have to know where we're going, and that then influences how the body is bound during the convertability checking.

He goes into more detail which I encourage you to follow the blog thread for.

Jeremy Likness

Windows Workflow Foundation (WWF) is a powerful programming model and designer for workflow processes. Using workflow is easier than some may believe.

I wanted to share a quick post relative to some practices I've found useful for sequential workflows, specifically around Inversion of Control (IoC) and unit testing.

In our shop we have several complex algorithms that are great candidates for sequential workflow. By using sequential workflow, we can:

  • Easily visualize the overall layout and flow of the process
  • Test the architecture of the flow (i.e. do we get to this node or that node) without having to worry with or deal with the underlying implementation of nodes within the flow
  • Refactor complex code simply by dragging and dropping nodes in the designer
  • Setup unit tests to ensure the integrity of the workflow persists as other systems are refactored

If you aren't familiar with workflow, I'd suggest searching for a few tutorials or walkthroughs. This is one of those technologies that is probably easier to learn by building some test projects than it is simply reading about it. The scope of this article will be how to build your sequential workflows for unit tests.

Interfaces and Delegates In

The workflow model lets you declare public properties on the main workflow that are then available to all of the nodes within that workflow. When you instantiate the workflow, you can send in a collection of name-value pairs map to public properties. For example, if I have an interface declared on my workflow:

...
public IMyInterface MyInterfaceImplemented { get; set; }
...

Then I can pass to workflow an instance of that interface like this:

...
Dictionary<string, object> myParams = new Dictionary<string, object>
   {
      {"MyInterfaceImplemented", new MyInterfaceImplementation()}
   };
...
_runtime.CreateWorkflow(typeof (MyWorkflow), myParams);

I'll get to what _runtime is in a bit. My point is, however, that any type of business logic you follow within your workflow should be hidden behind an interface and/or delegate. If you are passing in concrete instances, you are missing out on the power of being able to unit test your workflow structure.

You may have noticed that the code blocks in a sequential workflow, unless encapsulated as a custom entity, are actually events triggered by the workflow engine. For example, I might insert a Code workflow activity called AnalyzeUser. In the code behind, this appears as:

private void AnalyzeUser_ExecuteCode(object sender, EventArgs e)
{
}

In some cases you might be calling a method or service on an existing interface. However, other cases may be simple snippets of code. In order to keep your workflow completely pluggable, consider using a delegate. For example, if the analyze user takes a user parameter and then sets a flag in the workflow based on the result, instead of this:

private void AnalyzeUser_ExecuteCode(object sender, EventArgs e)
{
   _isOver30 = User.Age > 30;            
}

Try this:

// declare a delegate to analyze the user
public delegate bool AnalyzeUserDelegate(User user); 

// declare a method to set the delegate
public AnalyzeUserDelegate AnalyzeUserMethod { get; set; }

private void AnalyzeUser_ExecuteCode(object sender, EventArgs e)
{
   _isOver30 = AnalyzeUserMethod(User); 
}

Note we've encapsulated the action that is required (set a flag by analyzing the user) but we've removed the dependency of a concrete implementation. Why would I want to do this? Perhaps I am testing the overall workflow structure and want to know when it reaches the call to the delegate. I'm not concerned about whether it sets the users age, only if the method is reached. I can easily test for that situation like this:

...
bool delegatedCalled = false;

AnalyzeUserDelegate testMethod = (user) =>
   {
      delegatedCalled = true;
      return true;
   };

myParams.Add("AnalyzeUserMethod", testMethod);
...
instance.Start(); // start the worfklow
Assert.IsTrue(delegateCalled, "The method was invoked."); 
...

This allows you to separate testing the logic/flow of the workflow from the implementation of the various nodes within the workflow.

Properties Out

We talked about how to get implementation into the workflow, now let's talk about what to get out. Even if your workflow does not "return" a value to the outside world, you should consider exposing some properties to indicate key milestones within the workflow. One of our workflows involves assigning an asset to a location. The workflow itself only needs to perform the actual assignment. There is no "output" other than the changes to the system itself. However, for testing purposes, we expose certain values such as the location assigned and a flag that indicates whether an assignment was successful. This allows us to test the outcome, like this:

...
public bool WasAssigned { get; set; }
...
instance.Start(); // start the workflow
Assert.IsTrue((bool)results["WasAssigned"]); 

That example is a simple test of whether or not a successful assignment took place.

Wiring the Tests

One thing I've noticed is that few people realize workflows are very easy to test. There are many ways to trigger a workflow (events, schedules, etc). The standard examples I've seen online involve launching the engine in potentially a different thread altogether. Fortunately, the engine is extensible and there is a service shipped with the runtime that allows you to run it in an almost-synchronous way.

The first thing to do is set up references to the run time and the service that allows for the immediate workflow execution:

...
private WorkflowRuntime _runtime; 
private ManualWorkflowSchedulerService _scheduler; 
...

In your test setup, you'll instantiate the runtime and add the manual service:

[TestInitialize]
public void TestInitialize()
{
   _scheduler = new ManualWorkflowSchedulerService(); 
   _runtime = new WorkflowRuntime(); 
   _runtime.AddService(_scheduler); 
}

Be sure to tear down the workflow after the test is run:

[TestCleanup]
public void TestCleanup()
{
    if (_runtime != null && _runtime.IsStarted)
    {
        _runtime.StopRuntime();
    }

    if (_runtime != null)
    {
        _runtime.Dispose();
    }
}

Now you can wire up your test. If you want to be able test the output results as I mentioned above, you need to bind to the WorkflowCompleted event:

...
Dictionary<string, object> results = null;
_runtime.WorkflowCompleted += delegate(object sender, WorkflowCompletedEventArgs wce) { results = wce.OutputParameters; };
...

This will take all public properties and dump them by name and value into the results variable for inspection. The next thing is simply to create an instance and run it, like this:

WorkflowInstance instance = _runtime.CreateWorkflow(typeof (MyWorkflow), myParams);
instance.Start();
ManualWorkflowSchedulerService schedulerService = _runtime.GetService<ManualWorkflowSchedulerService>();
schedulerService.RunWorkflow(instance.InstanceId);
Assert.IsNotNull(results);

The results test ensures the workflow successfully ran.

Now I can test my workflow structure using a mocking framework like Moq. Moq makes it easy to inject a test object and verify whether or not it was called. If I have an interface called IMyUserServices and I am expecting the workflow to call a method called ValidateUser, I would simply load it up like this:

Mock<IMyUserServices> myUserServices = new Mock<IMyUserServices>(); 
Dictionary<string, object> myParams = new Dictionary<string, object> 
   {
      { "MyUserServicesImplemented", myUserServices.Object }
   };
// set up the call to always return true
myUserServices.Setup(svc => svc.ValidateUser(It.IsAny<User>())).Returns(true); 
...
instance.Start();
...
// make sure we called it
myUserServices.Verify(svc => svc.ValidateUser(It.IsAny<User>()), Times.Once());
...

Obviously going through all of the features and functionality of mock frameworks is outside of the scope of this post, but I wanted to share how easy these tools make it to create powerful, granular tests. I am able to wire up the entire complex workflow and test that the flow works as expected before every writing a line of actual implementation. Then, it becomes simple to implement the code and write unit tests for each atomic piece of functionality. This then makes it easy to test and implement complex solutions by breaking them into simple parts.

Finally, I'll leave you with a little snippet of unit testing wisdom I recently learned. A stub is something you inject to make a test run. A mock is something you check the state of to validate your test. Often people refer to stubs as mocks, but if you aren't inspecting the stub for success, it's a stub. If you are checking it for something (state, output, exception) then it is a mock.

Jeremy Likness