Blog Archives

Extending the Func<T> delegate in .Net 3.5

Today I was working with the Func<T> delegate in my code. I was testing it at my local development machine in a .Net 4.0 console application. (Side information: I was trying to create a sort of overloaded methods which end up in a generic caching method, that has the ability to call the orginal method to get data when there is no data found in the cache.)

My data method has five arguments in the signature and I was writing the following methods:

Generic caching method:

private static TResult PerformCaching<TResult>(Func<TResult> func, string cacheKey)
{
    var cachedData = Get<object>(cacheKey); // <= check if there is data in the cache. 

    if (cachedData == null)
    {
        return func.Invoke(); // <= if not invoke the delegate. 
    }

    return (TResult)cachedData;
}

Public caching method:

public static TResult PerformCaching<TResult, T1, T2, T3, T4, T5>(Func<T1, T2, T3, T4, T5, TResult> func, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, string cacheKey)
{
    return PerformCaching(() => func(arg1, arg2, arg3, arg4, arg5), cacheKey);
}

 

Running this in my .Net 4.0 console application works like a charm. However when I tried to implement this in our SharePoint 2010 project, which is running .Net 3.5 it’s giving me an error in my Error console:

Using the generic type ‘System.Func<TResult>’ requires 1 type arguments

Ok, time to grab reflector and see what’s happening under the hood: I have loaded the .Net 3.5 System.Core.dll manually. (In my case Reflector is starting up with default .Net 4.0) I see the following:

SystemCoreNet35

Both Action<T> and Func<T> have a maximum support for four generic arguments in .Net 3.5.

 

Okay, let’s compare this to .Net 4.0 where my example with five arguments is working like a charm.

SystemCoreNet40

 

From .Net 4.0 on there is support for 16 generic parameters in your Func<T> delegate. Ok, very nice this support in .Net 4.0, but SharePoint 2010 is still running .Net 3.5 and probably will not be updated to .Net 4.0. How can we fix this issue in .Net 3.5?

Well, that will be very easily been fixed with one line of code Emoticon met brede lach.

In our code we add ourselves a Func<T> delegate with the five needed generic arguments like below:

public delegate TResult Func<T1, T2, T3, T4, T5, TResult>(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5); 

Now you can compile your .Net 3.5 project and it’s supporting this five arguments Func<T> delegate. Now say how easy was that?

One of the issues that interests me is the part that when I look into the .Net 4.0 System.Core DLL, the Func<T> delegate starts with Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, TResult> and not with Func<T1, TResult>. I tried to found out where the other Func<T>’s have gone, and found out that these have a TypeForwardedFrom attribute like below:

[TypeForwardedFrom("System.Core, Version=3.5.0.0, Culture=Neutral, PublicKeyToken=b77a5c561934e089")]

The link gives the explanation I think very clear `Type forwarding allows you to move a type to another assembly without having to recompile applications that use the original assembly.`

Well that´s it about extending the Func<T> delegate, hope it will be helpful for you. If you have any questions or remarks please let me know in the comments.