Func<T> has been in .NET for a while, but with the arrival of LINQ it’s moved into the limelight as main performer that makes Lambda expressions work. Func<T> is basically a generic delegate that makes it extremely easy to create all sorts of custom delegate signatures without having to explicitly implement the delegates separately.
Events
How often have you lamented the fact that you have to create a custom delegate for an event that needs to fire a method that uses non-typical event arguments? Traditionally you had to create the method and also create a delegate that matched the signature which is a bit verbose at best. Typical event setup code looks something like this:
public event delInvoiceCalculation CalculateTax;
public delegate decimal delInvoiceCalculation(wws_Invoice invoice);
public virtual decimal OnCalculateTax(wws_Invoice invoice)
{
var calcTax = CalculateTax;
if (calcTax != null)
return calcTax(invoice);
return invoice.Tax;
}
You have to declare a separate delegate and provide the appropriate signature to match the event function that should be called.
Using Func<T> this code can be made a bit cleaner by removing the extra delegate. Here’s another implementation for a similar method using the same signature but using Func<T> or more specifically in this example, Func<T,TResult>
public event Func<wws_Invoice,decimal> CalculateHandling;
public virtual decimal OnCalculateHandling(wws_Invoice invoice)
{
// TODO: provide logic here
var calcHandling = CalculateHandling;
if (calcHandling != null)
return calcHandling(invoice);
return Entity.Handling;
}
Func<T> simplifies the event signature a bit by removing the explicit delegate declaration and instead using the generic Func<T,TResult> implementation that allows you to create a custom delegate signature directly on the event. Not only does it save a little bit of code typing, but I also find this easier to see what’s going because it is more explicit in a single statement compared the first snippet where delegate and event declaration are separate (and often completely separated physically because the delegate is reused by multiple events).
Func<T> is a generic function signature/delegate and it works by implementing a delegate by way of its generic parameters. The last generic parameter provided is always the type of the return value (decimal above). Any preceeding generic parameters (up to 4 in Func<T>’s overloads) become the types of input parameters. In this case my signature is for Func<T,TResult> where T is my invoice entity and TResult is bool.
In this respect:
Func<wws_Invoice,decimal>
is equivalent to:
public delegate decimal delInvoiceCalculation(wws_Invoice invoice);
except it doesn’t have to be explicitly declared.
Func<T> in LINQ
Delegates are generally easy to understand but it’s one of those features we don’t use all that often and so it’s easy to forget how they work and what we need them for. Well we know LINQ is full of them – most LINQ operators like .Where() and OrderBy() and Select() to name a few all rely on Func<T> signatures for Lambda expressions. Between Func<T> delegate signatures and lamda expressions statements like this:
Context.wws_Items.Where( itm => itm.Sku == sku );
become possible and quite readable once you get over the initial weirdness of the => operator. What you’re looking at in the Where clause is actually an implemenation of Func<T,bool>:
.
The input parameter is the the enumerable type (wws_Item from the List<wws_Item> and the return value is bool. The return value is inferred by the compiler and so only the input parameter is used (itm =>) in the lambda expression’s left side. Func<T> is a key feature to make LINQ workable using terse code.
Note that if you use LINQ to SQL or LINQ to Entities Func<T> based parameters to any LINQ commands require an Expression wrapper that wraps the Func<T> expression. This is because these tools delay executing the expressions until a later point in time when the expressions are parsed into some other format (SQL command, Entity SQL or whatever the expression engine uses).
This actually tripped me up yesterday and was what got me on to writing up this content. In my business layer I have basic CRUD operations including the ability to load entities without running a full LINQ command. There’s a base implementation that takes a LINQ expression as a parameter that is passed to a LINQ .Where() method that executes the actual query. At first I passed a Func<T> argument but I quickly found out that this doesn’t actually work – the result from the LINQ to SQL query always returned null. The reason: It’s not an expression that was passed but just a predicate.
I had to make sure the method was declared correctly using an Expression and the correct code that works looks like this:
protected virtual TEntity LoadBase(Expression<Func<TEntity, bool>> whereClauseLambda)
{
SetError();
try
{
TContext context = Context;
// If disconnected we'll create a new context
if (Options.TrackingMode == TrackingMode.Disconnected)
context = CreateContext();
Entity = Context.GetTable<TEntity>().Where(whereClauseLambda).SingleOrDefault();
if (Entity != null)
OnLoaded(Entity);
return Entity;
}
catch (InvalidOperationException)
{
// Handles errors where an invalid Id was passed, but SQL is valid
SetError("Couldn't load entity - invalid key provided.");
Entity = null;
return null;
}
catch (Exception ex)
{
// handles any other sql errors
Entity = null;
SetError(ex);
}
return null;
}
This makes it super easy to create custom load methods that all use the common LoadBase method and so inherit its behavior. in most cases it becomes as trivial as this:
/// <summary>
/// Loads an individual item by sku
/// </summary>
/// <param name="sku"></param>
/// <returns></returns>
public wws_Item LoadBySku(string sku)
{
return this.LoadBase(itm => itm.Sku == sku);
}
which is pretty nice and consistent.
Easy Async
Here’s another useful example of how Func<T> can make life a lot easier. For example, kicking off an async delegate with Func<T> becomes a single line operation which makes it a snap to turn just about any operation into an async operation like this async update routine:
public void LogSnippetViewAsync(string snippetId, string ipAddress, string userAgent)
{
Func<string, string, string, bool> del = this.LogSnippetView;
del.BeginInvoke(snippetId, ipAddress, userAgent, null, null);
}
public bool LogSnippetView(string snippetId, string ipAddress, string userAgent)
{
if (string.IsNullOrEmpty(userAgent))
return false;
userAgent = userAgent.ToLower();
if (!(userAgent.Contains("mozilla") || !userAgent.StartsWith("safari") ||
!userAgent.StartsWith("blackberry") || !userAgent.StartsWith("t-mobile") ||
!userAgent.StartsWith("htc") || !userAgent.StartsWith("opera")))
return false;
this.Context.LogSnippetClick(snippetId, ipAddress); // stored proc
return true;
}
Here’s Func<T1,T2,T3,TResult> is used to specify 3 parameters (3 strings) and a return value of bool. del is the Delegate declaration and we’re pointing it at the LogSnippetView method to execute. Then BeginInvoke is called to asynchronously launch the method so it runs in the background on a thread pool thread.
Again, using Func<T> avoids having to explicitly declare a delegate separately and instead you can directly declare the delegate signature via Func<T> inline which is easier to read and understand – at least to me.
Sometimes it’s the little things that make life easier and Func<T> is one of those.
Other Posts you might also like