Another really common and useful delegate is the Func delegate. This delegate has many overloads which all return a result. They differ in the number of parameters which they can be passed:

One scenario in which I have used this delegate is in a SessionState service which I wrote recently, effectively making SessionState strongly typed. By way of example, I have simplified that idea into a Console application which uses a Dictionary collection instead of HttpContext.Current.Session. First, I created the MemoryBucket class:
internal class MemoryBucket
{
private Dictionary<string, object> items;
internal MemoryBucket()
{
items = new Dictionary<string, object>(StringComparer.Ordinal);
}
internal void SetValue<T>(string key, T value)
{
if (!this.items.ContainsKey(key))
{
items.Add(key, value);
}
else
{
items[key] = value;
}
}
internal T GetValue<T>(string key, Func<T> createDefault)
{
T retval;
if (!ReferenceEquals(null, items))
{
if (items.ContainsKey(key) && items[key].GetType() == typeof(T))
{
retval = (T)items[key];
}
else
{
retval = createDefault.Invoke();
items[key] = retval;
}
return retval;
}
else
{
throw new NullReferenceException("There is no Memory object available.");
}
}
}
Looking at the GetValue method, if the value passed into this method is either null, or not the same type as the item which correlates to that key, a default value is returned. That default value is determined by the method (or lambda) which the calling code passes in as the 2nd parameter. So, the delegate gives the power to the calling code to control how the default value is generated. For example:
static void Main(string[] args)
{
MemoryBucket bucket = new MemoryBucket();
bucket.SetValue("My Name", "dave");
Console.WriteLine(bucket.GetValue("My Name", () => "David"));
bucket.SetValue("My Name", 10);
Console.WriteLine(bucket.GetValue("My Name", () => "David"));
Console.Write("\nPress any key to kill console...");
Console.ReadKey();
}
As you can see, the second time I call GetValue follows a call to SetValue which sets the “My Name” item to 10. As the System.Int32 type is not of the same type as the System.String type, the default value will be returned. That value being the string “David”, which is the return value in the lambda expression.