Basically they specify a method as a type, including signature specification.
I use them all the time. Here are some real world examples:
I have custom web controls. If the control is given a Label then both controls are wrapped together. I can pass Render methods as delegates:
public delegate void HtmlRenderMethod(HtmlTextWriter writer);
public override void Render(HtmlTextWriter writer){
if(!string.IsnullOrEmpty(Label)){
RenderWrapper(base.Render,writer);
}
else{
base.Render(writer);
}
}
private void RenderWrapper(HtmlRenderMethod method, HtmlTextWriter writer){
writer.RenderOpenTag("div");
RenderLabel(writer);
method(writer);
writer.RenderCloseTag();
}
My render methods are far more complex that this. For example I have the base ValidatedTextbox that inherits TextBox but I have other controls that inherit from ValidatedTextbox. If I want access to the TextBox Render method without having to go through the ValidatedTextbox render method then I can just save the original method in a protected variable and call it from any ancestor.
I have also started my custom workflow engine. This will operate on a message-to-method basis. I need to know what method handles what kind of message. To do this I create a delegate and create a dictionary<message,method>:
public delegate Engine.WorkflowResult MessageHandler(IMessage message);
public class MessageHandlerList : Dictionary<type,>
{
public Engine.WorkflowResult TryParse(IMessage message)
{
if (!ContainsKey(message.GetType()))
return WorkflowResult.Wait;
return this[message.GetType()](message);
}
public new bool ContainsKey(Type key)
{
return Keys.Any(k => k.GUID == key.GUID);
}
public new MessageHandler this[Type key]
{
get { return base[Keys.Single(k => k.GUID == key.GUID)]; }
set { base[Keys.Single(k => k.GUID == key.GUID)] = value; }
}
}
...
private MessageHandlerList _messageHandlers {get;set;}
public void Initialize(){
_messageHandlers = new MessageHandlerList();
_messageHandlers.Add(ProcessStartMessage,ProcessStartHandle);
_messageHandlers.Add(ProcessEndMessage,ProcessEndHandle);
}
public Engine.WorkflowResult ParseMessage(IMessage message){
return _messageHandlers.TryParse(message)
}
private Engine.WorkflowResult ProcessStartHandle(IMessage message){
if(!message.Deserialized)
message.Deserialize();
ProcessStartMessage startMessage = (ProcessStartMessage)message;
}
private Engine.WorkflowResult ProcessEndHandle(IMessage message){
if(!message.Deserialized)
message.Deserialize();
ProcessEndMessage startMessage = (ProcessEndMessage)message;
}
...
I also use delegates when I wrap transactions on the database. I use a more open delegate so I can get any return type I like, so long as the core delegate returns void:
public delegate void Transaction();
public static void TransactionWrapper(Transaction transaction)
{
var options = new TransactionOptions
{
IsolationLevel = IsolationLevel.Snapshot,
Timeout = TimeSpan.FromSeconds(120)
};
using (var scope = new TransactionScope(TransactionScopeOption.Required, options))
{
transaction();
scope.Complete();
}
}
...
public List<message> SelectAllDue(DatabaseContext db = null){
if(db==null)
db = new DatabaseContext();
List<messages> result = null;
TrasactionWrapper(()=>{
var query = db.Messages;
query = query.Where(m=>m.Due < DateTime.Now);
result = query.ToList();
}
return result
}
...</messages></message>
There are many other clever things you can do as well. You can have composite delegate groups even.
Every Lamda expression is technically a delegate
These are a few 'real world' examples, that I have trimmed for simplicity.