Skip to content

Delegates

Mario Gutierrez edited this page Jan 7, 2017 · 2 revisions
// Declaring a delegate type.
public delegate string MyDelegate(bool b, int n);

// Declaring and initializing a delegate variable.
MyDelegate mdel = new MyDelegate(SomeMethod);

// Alternatively, you can just supply the method name.
// This is called "method group conversion syntax".
MyDelegate mdel = SomeMethod;

// Delegates can be combined to call multiple methods.
mdel += AnotherMethod;
mdel += OrAnotherDelegate;

// Invoking the delegate.
mdel();

Generic Delegates

public delegate void GenericDel<T>(T arg);

public void MyFunc(string a) { }
GenericDel<string> strTarget = MyFunc;

Action<...> and Func<...>

These two are out-of-the-box, generic delegate types for simplifying the definition of a delegate.

Action<...>

  • Takes up to 16 arguments.
  • Can only point to functions with a void return type.
static void DisplayMessage(string msg, ConsoleColor col) { }
Action<string, ConsoleColor> target = DisplayMessage;
target("hello", ConsoleColor.Blue);

As you can see in the example, the types in the generic parameter list define the types of the parameters the delegate methods take in.

Func<...>

  • Takes up to 16 arguments.
  • The last generic parameter is the return type.
static string IntToString(int a) { }
Func<int, string> target = IntToString;
string s = target(5);

Predicate

Defined in the System as such:

public delegate bool Predicate<T>(T obj);

This is used in places like List.FindAll().

Events

Events are a special kind of multicast delegate that can only be invoked from within the class or struct where they are declared (the publisher class).

public delegate string MyDelegate(int a);
public event MyDelegate MyEvent;

EventArgs

Microsoft's recommended pattern for how to publish data with a delegate.

public delegate void MyDelegate(object sender, MyEventArgs e);
public event MyDelegate MyEvent;

public class MyEventArgs
{
  public MyEventArgs(string s) { Text = s; }
  public string Text { get; private set; } // readonly
}

// Variation
public class MyEventArgs
{
  public MyEventArgs(string s) { text = s; }
  public readonly string text;
}

// Now when you raise an event to listeners. (In the publisher class...)
MyEvent(this, new MyEventArgs("Hey, this is some event data."));

EventHandler

Given the recommended (object sender, EventArgs e) pattern, there is a generic event type Microsoft provides to streamline this.

public event EventHandler<MyEventArgs> MyEvent;

You don't need to define the delegate in this case.

Delegates: Behind the Scenes

The compiler generates a class for a delegate type.

sealed class MyDelegate : System.MulticastDelegate
{
  // Basic synchronous invocation.
	public string Invoke(bool b, int n);

	// The other two are for asynchronous use.
	public IAsyncResult BeginInvoke(bool b, int b, AsyncCallback cb, object state);
	public string EndInvoke(IAsyncResult result);
}

The MulticastDelegate class is defined as such:

public abstract class MulticastDelegate : Delegate
{
	// Returns the list of methods "pointed to"
	public sealed override Delegate[] GetInvocationList();

	// Overloaded operators.
	public static bool operator ==(MulticastDelegate d1, MulticastDelegate d2);
	public static bool operator !=(MulticastDelegate d1, MulticastDelegate d2);

	// Used internally to manage the list of methods maintained by the delegate.
	private IntPtr _invocationCount;
	private object _invocationList;
}

The Delegate class is defined as such:

public abstract class Delegate : ICloneable, ISerializable
{
	// Methods to interact with the list of functions.
	public static Delegate Combine(params Delegate[] delegates);
	public static Delegate Combine(Delegate a, Delegate b);
	public static Delegate Remove(Delegate source, Delegate value);
	public static Delegate RemoveAll(Delegate source, Delegate value);

	// Overloaded operators.
	public static bool operator ==(Delegate d1, Delegate d2);
	public static bool operator !=(Delegate d1, Delegate d2);

	// Properties that expose the delegate target.
	public MethodInfo Method { get; }
	public object Target { get; }
}
  • The '+=' operator is syntax sugar for the Combine() method.
  • The '-=' operator is syntax sugar for the Remove() method.
  • 'Method' gets target method details.
  • 'Target' gets object details if the target method belongs to an instance.
Clone this wiki locally