Demystifying the Func in C#
Until recently, I thought doing any kind of functional programming in C# was a nightmare. The syntax for using delegates always seemed very clumsy to me. I would start with this grand idea of passing in a delegate to be called when I wanted, but would end up stumbling over the syntax for hours on end. Coming up through the ranks of .NET programming since v1.1, all of those examples of using delegates made things like asynchronous programming seem super hard. If only there was a better way…
Over the past few years working at Method, I’ve had the privilege of working on projects outside the .NET world. Getting outside of my comfort zone and taking a stab at things like nodejs has really helped me better understand C#. One of those things has been the concept of passing functions around as variables or objects. In a language like JavaScript where you are doing a lot of things like AJAX calls, the concept of a callback function is a very common practice. In C#, however, it can get pretty hairy until you discover the underpinnings of the lambda.
C# Lambdas
Most C# dev’s use lambdas all the time in writing LINQ queries. Since .NET 3.5 this has become a very common practice: var result = someList.Select(it => it.IsActive);
But to really understand its power you have to break it down to the components that make it up. Looking to the MSDN documentation for the .Select
method you see a method signature that doesn’t look exactly like you would expect.
public static IEnumerable<TResult> Select<TSource, TResult>(
this IEnumerable<TSource> source,
Func<TSource, TResult> selector
)
What is this Func<TSource, TResult> selector
thing? Why didn’t we have to specify those generic classes <TSource, TResult>
when calling Select
? I believe the confusing part of this is that the C# compiler will infer the Generic Types for you most of the time when using Select
. So this could be rewritten as .Select<SomeClass, bool>(it => it.IsActive)
, which says:
- We’re selecting from an
IEnumerable
of typeSomeClass
(SomeClass
maps toTSource
above). - Passing an item in that collection (defined as
it
) to the lambdait => it.IsActive
. - Then returning the
bool
propertyIsActive
(bool
maps toTResult
above).
Since most of the time the generic type declaration on Select
is not required, we don’t realize we are actually defining the return type and the parameter type(s) of the lambda. This is a key concept to being able to reuse the meat of a lambda which is the Func
.
The Func
A Func
in C# is a way to define a method in-line that has a return value. There is a similar concept of an Action
that doesn’t have a return value, but we’ll get to that in a sec. The return value’s type is always the last generic parameter on the Func
‘s definition. All the other generic parameter types are the parameters you are passing to the Func
. So in theory, if we want to reuse the selector from the above code in more than one place, we can define it as a Func
:
Func<SomeClass, bool> isActiveSelector = it => it.IsActive;
Now when calling our Select
on SomeClass
, we can pass it our Func
:
var result = someList.Select(isActiveSelector);
In this simple example, it doesn’t make that much difference as far as the code goes, but if I was using a more complex return type, this could be crucial for code maintainability. All in all though, reusing selectors isn’t all that sexy. Where it gets interesting for me is when it dawned on me that I could define a Func
or an Action
and pass it in as a parameter to a method (like so easily done in JavaScript).
Imagine there is a utility method that I would like to define, that would wrap some database calls in a transaction. In this method I know I’m going to always have to open a transaction, run some code that will always be different, and then commit or rollback the transaction. Now how do I do this, you say? Did I hear inheritance? Nah, lets do it with an Action
:
public void WrapInTransaction(Action dbCalls)
{
using (ITransaction transaction = _session.BeginTransaction())
{
try
{
dbCalls();
transaction.Commit();
}
catch(Exception exception)
{
//do something with the exception
transaction.Rollback();
}
}
}
Then I can call this method with a nice, cozy lambda:
WrapInTransaction(() =>
{
Update(entity);
LogToAuditTable(entity);
});
A couple things to note about this syntax here.
- An
Action
can be used with no parameters, which is what you see inWrapInTransaction(Action dbCalls)
. - A lambda expression that doesn’t take any parameters starts with
() =>
. - Lambdas can also be multiline! To create a multiline lambda, just open the block with a
{
(and be sure to close it with a}
). Also each line in a multiline lambda has to be terminated with a;
.
Boom! We are now doing some functional programming in C#. This is awesome because it can really help reduce code duplication. If you catch yourself always starting or ending a method with the same lines, you can refactor that into a method that takes in an Action
or Func
. Or take this and apply it to the Task paradigm and do some cool asynchronous programming.