Recently I’ve been experimenting with the use of the Func<T> class, and so far I’m loving it. I’ve noticed however that more and more I’m beginning to use it instead of actually using an instance of T, so I wanted to ask; what’s the overhead of using Func<T> vs T? I know this is a somewhat generic question, as T can be anything, so I guess that question should maybe be focused towards, what is the overhead of passing a function, rather than an instance of a simple object?
For the sake of argument, let’s assume the following.
Our mock object, T
public class Person
{
private string _name = string.Empty;
private int _age = 0;
private bool _isMale = true;
public Person(string name, int age, bool isMale)
{
this.Name = name;
this.Age = age;
this.IsMale = isMale;
}
public string Name
{
get { return this._name; }
set { this._name = value; }
}
public int Age
{
get { return this._age; }
set { this._age = value; }
}
public bool IsMale
{
get { return this._isMale; }
set { this._isMale = value; }
}
}
Now, let’s say we have a pretty extension method on IDictionary, that selects the value by the key, or a default value. The pseudocode could be described as follows:
Is the key found in the KeyValuePair collection
Yes, return the value
No, return the default
Option 1. Our extension method using an instance of T
public static TValue GetValueOrDefault<TKey, TValue>(this IDictionary source, TKey key, TValue @default)
{
if (source.ContainsKey(key))
{
return source[key];
}
return @default;
}
// usage
var myValue = myDictionary.GetValueOrDefault("Richard", new Person());
Option 2. Our extension method using Func<T>… mmm, pretty!
public static TValue GetValueOrDefault<TKey, TValue>(this IDictionary source, TKey key, Func<TValue> defaultSelector)
{
if (source.ContainsKey(key))
{
return source[key];
}
return defaultSelector();
}
// usage
var myValue = myDictionary.GetValueOrDefault("Richard", () => new Person("Richard", 25, true));
Comparison
Comparing the above options, it’s clear that there are potential benefits of both. Option 1 is slightly easier to read, however I’m currently loving the usage of Func<T>, and therefore to me option 2 seems ideal. I guess I’m considering it a lazily-instantiated parameter, that is only executed when it’s needed, therefore saving on efficiency, but am I right?
This is the code I used for the benchmark:
Calling each extenssion method 100000000 times (without finding an entry, hence causing Func to be executed each time) gives the following result:
T– 10352 msFunc<T>– 12268 msCalling each extenssion method 100000000 times (and finding an entry, hence not calling Func at all) gives the following result:
T– 15578 msFunc<T>– 11072 msHence, which one performs quicker depends of how many instantiations you save and how expensive is each instantiation.
Optimising the code a bit by reusing the default person instance gives 6809 ms for
Tand 7452 forFunc<T>:So, in theory (if you take instantiation out of the equation), saving a hop in the call stack gives you some performance gain, but in practice, this gain is negligible.