Efficiency: Func<T>, Vs instance of T
.net, c#, functional-programming, generics
Solution
This is the code I used for the benchmark:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Linq.Expressions;
namespace ConsoleApplication3
{
using System.Collections;
using System.Diagnostics;
using System.Globalization;
using System.Numerics;
using System.Xml.Linq;
public class Program
{
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;
}
}
}
private static void Main(string[] args)
{
var myDictionary = new Dictionary<string, Person>();
myDictionary.Add("notRichard", new Program.Person("Richard1", 26, true));
myDictionary.Add("notRichard1", new Program.Person("Richard2", 27, true));
myDictionary.Add("notRichard2", new Program.Person("Richard3", 28, true));
myDictionary.Add("notRichard3", new Program.Person("Richard4", 29, true));
// usage
Stopwatch sw = new Stopwatch();
sw.Start();
for(int i = 0; i < 100000000; i++)
{
var myValue = myDictionary.GetValueOrDefault("Richard", new Program.Person("Richard", 25, true));
}
sw.Stop();
Console.WriteLine(sw.ElapsedMilliseconds);
sw = new Stopwatch();
sw.Start();
for (int i = 0; i < 100000000; i++)
{
var myValue = myDictionary.GetValueOrDefault("Richard", ()=> new Program.Person("Richard", 25, true));
}
sw.Stop();
Console.WriteLine(sw.ElapsedMilliseconds);
Console.ReadKey();
}
}
public static class Ex
{
public static TValue GetValueOrDefault<TKey, TValue>(this Dictionary<TKey, TValue> source, TKey key, TValue @default)
{
if (source.ContainsKey(key))
{
return source[key];
}
return @default;
}
public static TValue GetValueOrDefault<TKey, TValue>(this Dictionary<TKey, TValue> source, TKey key, Func<TValue> defaultSelector)
{
if (source.ContainsKey(key))
{
return source[key];
}
return defaultSelector();
}
}
}
Calling each extenssion method 100000000 times (without finding an entry, hence causing Func to be executed each time) gives the following result:
`T` - 10352 ms
`Func<T>` - 12268 ms
Calling each extenssion method 100000000 times (and finding an entry, hence not calling Func at all) gives the following result:
`T` - 15578 ms
`Func<T>` - 11072 ms
Hence, 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 `T` and 7452 for `Func<T>`:
Stopwatch sw = new Stopwatch();
var defaultPerson = new Program.Person("Richard", 25, true);
sw.Start();
for(int i = 0; i < 100000000; i++)
{
var myValue = myDictionary.GetValueOrDefault("Richard", defaultPerson);
}
sw.Stop();
Console.WriteLine(sw.ElapsedMilliseconds);
sw = new Stopwatch();
sw.Start();
for (int i = 0; i < 100000000; i++)
{
var myValue = myDictionary.GetValueOrDefault("Richard", () => defaultPerson);
}
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.
Problem
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?