Miguel A. Castro's Blog

# Thursday, August 12, 2010

I want to show you something that many of you may be familiar with since it’s really not new to .NET 4 (well not all of it anyway).  Be that as it may, I think it falls into the category of “still not too regularly used”.  The technique I’m going to show you has to do with Lambda expressions in my examples but can certainly be accomplished with anonymous delegates.

I’m not here to show you an intro to Lambda expressions, but instead how to mix them with the Action<T> and Func<T> delegates for some cool coding techniques.  But first, an introduction to these delegates:

The oldest and simplest is Action<T>.  This delegate was introduced back in .NET 2.0 and could be used with anonymous delegates.  The signature of this delegate is:

public delegate void Action<T>(T arg);

 

With this pretty free-form signature, the delegate is pretty useful in any scenario where you need to define methods with single signatures.  Later after my introduction, I’ll show you how to use this delegate in a cool technique.  Now, in .NET 4 Microsoft proved that their developers watch entirely too much Mythbusters, by falling into the creed of “What’s worth doing, is worth over-doing”.  I’m not being critical here; I fall into that one all the time myself.  In .NET 4, Microsoft expanded on the Action<T> idea and came out with Action<T1, T2>.  How’s that overdoing it you ask?  Well gentle reader, that’s not the overdoing part, this is: Action<T1, T2, T3>, Action<T1, T2, T3>, and Action<T1, T2, T3, T4>.  If you still think that’s not too much, it actually goes out to T8.

The signatures of these delegates are as you may guess, the same as the original but with additional arguments.  For example:

public delegate void Action<T1, T2, T3>(T1 arg1, T2 arg2, T3 arg3);


I guess you can call this a “one size fits all” delegate.

Also in .NET 4 came the introduction of the Func<TResult> delegate.  The signature of this delegate looks like this:

public delegate TResult Func<TResult>();


There’s also one that accepts a single argument called, Func<T, TResult>, whose signature looks as follows:

public delegate TResult Func<T, TResult>(T arg);

 

And as you can guess, there are others.  Specifically, Func<T1, T2, TResult> and so on all the way to T8 as well.

From what you can see here, the difference between the two delegates is that Action does not offer a return type and Fun does.  So what’s this good for?  Let me show you.

I’ll start with the Action delegate since its lack of return type make for a bit simpler example.  The Action delegate lets you assign a piece of code to a variable for later invocation.  The type(s) defined in the generic determine the types of the arguments you use in either an anonymous delegate or a lambda expression.  For my examples, I’m going to use lambda expressions and keep things current.  Check out this code sample:

 

Action<IProcessable> process = (processable =>
{
    processable.PerformSomethingHere();
    foreach (var item in processable.SubItemList)
    {
        item.DoSomethingWithItem();
    }
});

 

This code is designed to act upon any object that implements the IProcessable interface.  It simply calls a method defined by that interface then looks through a list property called SubItemList, which is also defined in the interface.  On each item in the list, it calls a method on that item.  This idea will be very similar to simply putting this code in its own method, then calling that method with any implementation of IProcessable.  However, if you have no need to use this code from multiple outside methods, yet still have to call it multiple times (as you’ll see in a second), defining it this way makes for great encapsulation and isolation.  So not let’s say I have an object hierarchy that looks something like this:

Parent.Children[x].GrandChildren

 

In other words, the Parent object has a collection of Child objects in a property called Children, and each child object has a collection of GrandChild objects in a property called GrandChildren.  The Parent, Child, and GrandChild classes all implement the IProcessable interface so I need to execute the code snippet you saw above on all these objects.  As I said, it’s easy enough to put the above-code in a method and just called that method from a for-each scenario on my Parent object, but I won’t need that code called from anywhere else and I want to keep all this encapsulated in my one method. I can use the processable variable and invoke it, sending into its argument any instance of the IProcessable interface.  The solutions is to do something like this:

 

Action<IProcessable> process = (processable =>
{
    processable.PerformSomethingHere();
    foreach (var item in processable.SubItemList)
    {
        item.DoSomethingWithItem();
    }
});

process.Invoke(Parent);

foreach(var child in Parent.Children)
{
    proces.Invoke(child);
    foreach (var grandChild in child.GrandChildren)
        process.Invoke(grandChild);
}

 

As you can see, the solution is simple and elegant and eliminates the need to have yet another method in your class.  If I wanted to pass in another value, like a boolean, into each invocation of the code snippet, I can use the Action<T1, T2> delegate.  the lambda expression would then have two variables in it.  Here’s the same code modified I the way I’ve just described:

 

Action<IProcessable, boolean> process = ((processable, b) =>
{
    processable.PerformSomethingHere();
    foreach (var item in processable.SubItemList)
    {
        item.DoSomethingWithItem();
        item.BooleanPropertu = b;
    }
});

process.Invoke(Parent, false);

foreach(var child in Parent.Children)
{
    proces.Invoke(child, true);
    foreach (var grandChild in child.GrandChildren)
        process.Invoke(grandChild, true);
}

 

It’s very important to wrap the two arguments prior to the lambda’s “goes to” operator using parentheses.  Pretty cool huh?  Yeah, I think so too Smile.  Let’s take a look at using the Func delegate in a very similar fashion.  Remember, this delegate defines a return type as well.

The usage scenario for this delegate would be pretty much identical as the previous, only you would have the need to return a value from the invocation.  So this time, let me share with you a real-world example on where I’m currently using this delegate.  First let me set the scene.

I have a situation where I have to obtain three different database schema query filters (strings) from an incoming dictionary of key-value pairs (IDictionary<string, string>).  The dictionary comes into a method and potentially contains three items keyed by “TableFilter”, “CommandFilter” and “ViewFilter”.  I say potentially because the incoming dictionary may not contain all of these keys, or none at all, but those that are present contain values that are needed in individual variables.  So for example, under normal, boring code circumstances, I would need to check the incoming dictionary (a variable called arguments) to see if it contains the key TableFilter.  If it does, I set its value in a string variable called stringFilter.  I need to repeat this for the other two keys I’m looking for.  Oh, and did I mention that the arguments variable can come into my method as null as well?  And, if either the key is not found in the dictionary or the entire dictionary comes in as null, I still need my string variable(s) but with an empty string as their value.

Fine, you’re thinking I can simply check arguments for null first, then do a “contains” check on each key and then set each variable accordingly.  Man would that be boring!  Let’s do it in a much cooler way:

 

Func<string, string> filterCheckAndSet = (key => 
{
    string filter = "";
    if (arguments != null && arguments.ContainsKey(key))
        filter = arguments[key];

    return filter;
});

string tableFilter = filterCheckAndSet.Invoke("TableFilter");
string commandFilter = filterCheckAndSet.Invoke("CommandFilter");
string viewFilter = filterCheckAndSet.Invoke("ViewFilter");

 

Here, you can see I’m defining my code snippet in a Func<T, TResult> delegate type, where the first generic defines what I’m sending into the code and the second defines what I’m returning.  As you can see, I default my return-type to an empty string, I check the dictionary against it being null and also containing the key I need.  The key is one of the arguments I will send into the piece of code.  If I find the key, I set the my return variable to the contents of that dictionary item and then return it; yes I can do a return inside code defined in a Func delegate type.  Later, I simply invoke the filterCheckAndSet variable, sending in each key, and using the return value in each string variable I need.

That’s it.  I’ve found myself using these techniques more and more.  But remember, the biggest argument you’ll find against this is that you can accomplish the same with additional method calls.  My argument is, yes you can, but if you don’t need a specific level of code re-use, try to limit the scope of the code as it provides better encapsulation.  Also, remember that the code snippets are stored in object variables so they can be passed around anywhere you want (should you actually have that particular need).

 

Until next time…

Thursday, August 12, 2010 6:39:10 PM (Eastern Daylight Time, UTC-04:00)  #    Comments [3] - - Follow me on Twitter
Dev Stuff
Thursday, August 12, 2010 7:14:05 PM (Eastern Daylight Time, UTC-04:00)
Nice Post, but i'm having a comment about your last code snippet in which you used the Func<T, TResult> delegate, the code is looking neat and reusable as you are pointing out, but on the other side what about the performance?

The ContainsKey function which you are calling on the Dictionary is O(n) and you call it 3 times for each filter value, I think if you make a single iteration on the dictionary to check your filter values would be better in Essene of performance.

Just thoughts :)
Amr Attia
Thursday, August 12, 2010 7:21:37 PM (Eastern Daylight Time, UTC-04:00)
Perhaps in this particular scenario. But I doubt the nano seconds would be noticeable. Besides, in my case, the arguments object can come in with many values and this method only cares about those three so a full iteration for items that may or may not be immediately found seemed a bit excess. But thanks and your comments are always welcome.
Sunday, September 05, 2010 11:55:13 AM (Eastern Daylight Time, UTC-04:00)
about the performance, it think it can be made faster using TryGetValue instead of ContainsKey, I think it's complexity is O(1)
and about using the Func<T, TResult> delegate, personally, I would've made a private method for it (an extension method would be cool too), I don't understand how can this make the code more re-usable than I need.
I think the Action and Func delegates' main use is for making methods were the calelr would specify how certain things should be done, like in LINQ's extension methods.
Comments are closed.
Search
Me & My Flair

Read all about me here.
Download my Resume here.

Check out where I am here.
 
Click on logos above for profiles.
Archive
<February 2012>
SunMonTueWedThuFriSat
2930311234
567891011
12131415161718
19202122232425
26272829123
45678910
Statistics
Total Posts: 36
This Year: 1
This Month: 1
This Week: 0
Comments: 80