Approfittando dell'influenza che mi tiene bloccato a letto, mi diverto a passare il tempo facendo qualche esperimento.
Una delle caratteristiche introdotte da C# 3.0 è quella degli "extension methods". Siccome tutti i tipi delegate derivano da System.MulticastDelegate, è possibile scrivere una serie di extension methods che aggiungono funzionalità a tutti i metodi (invocati attraverso un qualunque delegate).
Es:

public static class DelegateX
{
   public static object Delay(this MulticastDelegate fn, int delay, params object[] args)
   {
     
Thread.Sleep(delay);
     
return fn.DynamicInvoke(args);
  
}

   public static object Attempt(this MulticastDelegate fn, params object[] args)
  
{
     
try
      {
        
return fn.DynamicInvoke(args);
     
}
     
catch (Exception)
     
{
        
return null;
     
}
  
}
}

Delay permette di invocare un metodo dopo un certo ritardo. Attempt permette invece di eseguire un metodo "soffocando" una eventuale eccezione. Chiaramente è solo un esempio. Ciascuno può immaginare molti altri metodi di varia utilità. Vediamo ora un paio di esempi di invocazioni:Func<int, int> f0 = x => x * x;
Console.WriteLine(f0.Delay(1000, 2));

Func<int> f1 = () => { throw new Exception(); };
Console.WriteLine(f1.Attempt(0));