Callbacks in C#

Two options for you:

  1. Have the function accept a delegate (Action for a callback that doesn't return anything, Func for one that does) and use an anonymous delegate or Lambda Expression when calling it.

  2. Use an interface

Using a delegate/lambda

public static void DoWork(Action processAction)
{
  // do work
  if (processAction != null)
    processAction();
}

public static void Main()
{
  // using anonymous delegate
  DoWork(delegate() { Console.WriteLine("Completed"); });

  // using Lambda
  DoWork(() => Console.WriteLine("Completed"));
}

If your callback needs to have something passed to it, you can use a type parameter on Action:

public static void DoWork(Action<string> processAction)
{
  // do work
  if (processAction != null)
    processAction("this is the string");
}

public static void Main()
{
  // using anonymous delegate
  DoWork(delegate(string str) { Console.WriteLine(str); });

  // using Lambda
  DoWork((str) => Console.WriteLine(str));
}

If it needs multiple arguments, you can add more type parameters to Action. If you need a return type, as mentioned use Func and make the return type the last type parameter (Func<string, int> is a function accepting a string and returning an int.)

More about delegates here.

Using an interface

public interface IObjectWithX
{
  void X();
}

public class MyObjectWithX : IObjectWithX
{
  public void X()
  {
    // do something
  }
}

public class ActionClass
{
  public static void DoWork(IObjectWithX handlerObject)
  {
    // do work
    handlerObject.X();
  }
}

public static void Main()
{
  var obj = new MyObjectWithX()
  ActionClass.DoWork(obj);
}

Sounds like a perfect recipe for delegates - in particular, callbacks with delegates are exactly how this is handled in the asynchronous pattern in .NET.

The caller would usually pass you some state and a delegate, and you store both of them in whatever context you've got, then call the delegate passing it the state and whatever result you might have.

You could either make the state just object or potentially use a generic delegate and take state of the appropriate type, e.g.

public delegate void Callback<T>(T state, OperationResult result)

Then:

public void DoSomeOperation(int otherParameterForWhateverReason,
                            Callback<T> callback, T state)

As you're using .NET 3.5 you might want to use the existing Func<...> and Action<...> delegate types, but you may find it makes it clearer to declare your own. (The name may make it clearer what you're using it for.)

Tags:

C#

.Net

Callback