C# Delegates

A delegate is a type that represents references to methods with a particular parameter list and return type. When you instantiate a delegate, you can associate its instance with any method with a compatible signature and return type. You can invoke (or call) the method through the delegate instance.

Delegate types are delegate, Action and Func.

Multicast Delegate

All C# delegates have multicast capability, this means a single delegate instance can reference more than one target method. You can add or remove target methods using operators += or -=. Target methods are called in the order they were added to the delegate instance.

  1. Create the delegate
1
delegate void NumbersDelegate(int a, int b);
  1. Create methods the delegate will call, the need to have the same return type and parameters signature.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public class Foo
{
public void AddNumbers(int a, int b)
{
Console.WriteLine("AddNumbers: " + (a + b))
}

public void MultiplyNumbers(int a, int b)
{
Console.WriteLine("MultiplyNumbers: " + (a * b))
}

public void SubtractNumbers(int a, int b)
{
Console.WriteLine("SubtractNumbers: " + (a - b))
}
}
  1. Use the delegate with one method AddNumbers
1
2
3
4
5
6
7
var foo = new Foo();

// Delegate with initial target `AddNumbers`
NumbersDelegate numbersDelegate = foo.AddNumbers;

// Invoke delegate, this will call `AddNumbers`
numbersDelegate(5, 5);
  1. Multicast the delegate to have more than one target
1
2
3
4
5
numbersDelegate += foo.MultiplyNumbers;
numbersDelegate += foo.SubtractNumbers;

// Invoke delegate, this will call `AddNumbers`, then `MultiplyNumbers` and finally `SubtractNumbers`
numbersDelegate(5, 5);
  1. You can also remove targets from the delegate
1
2
3
4
numbersDelegate -= foo.MultiplyNumbers;

// Invoke delegate, this will call `AddNumbers`, then `SubtractNumbers` as it no longer points to `MultiplyNumbers`
numbersDelegate(5, 5);

Delegate As A Parameter

This was used in my windows event logger application.

  1. Create the delegate representing a method
1
public delegate void EventLogReaderDelegate(EventRecord record);
  1. Create the methods the delegate will point to
1
2
3
4
5
6
7
8
9
10
private void Count(EventRecord record)
{
// count logic that does something with `record`
// my app didnt actually do anything with `record` but there is a SO link below for an example that did, the principle is pretty much the same though.
}

private void Append(EventRecord record)
{
// append logic that does something with `record`
}
  1. Create a method that accepts the delegate as a parameter
1
2
3
4
5
6
7
8
9
10
11
12
private void ProcessReader(EventLogReader reader, EventLogReaderDelegate delegate)
{
EventRecord record;
while ((record = reader.ReadEvent()) != null)
{
using (record)
{
delegate(record);
}
}
reader.Seek(new SeekOrigin(), 0);
}
  1. Call ProcessReader and pass it the delegates as parameters
1
2
3
4
5
6
7
8
9
public List<EventLogModel> Go()
{
using (var reader = new EventLogReader(_filePath, PathType.FilePath))
{
ProcessReader(reader, Count);
ProcessReader(reader, Append);
}
return _returnValue;
}

Similar example from SO: https://stackoverflow.com/questions/2019402/when-why-to-use-delegates

References