A callback in C# is a mechanism for executing a method (or function) when a certain action is complete or a certain event occurs. It allows you to pass a reference to a method as an argument to another method, which can then call the referenced method at the appropriate time.
Callbacks can be implemented in C# using delegates, anonymous methods, or lambda expressions. They are commonly used to achieve asynchronous programming, event handling, or modular code design.
How Callbacks Work in C#
-
Delegate-based Callbacks: A delegate is a type that represents a method signature. You can use it to reference and invoke methods that match the signature.
// Delegate declaration public delegate void CallbackDelegate(string message); public class CallbackExample { public void PerformAction(CallbackDelegate callback) { // Simulating some work Console.WriteLine("Performing an action..."); // Invoking the callback callback("Action completed!"); } } public class Program { public static void Main(string[] args) { var example = new CallbackExample(); example.PerformAction(message => Console.WriteLine(message)); // Using a lambda expression as a callback } }
-
Event-based Callbacks: Events are a higher-level abstraction that use delegates under the hood. They are typically used for signaling when something happens.
public class EventExample { public event Action<string> OnActionCompleted; public void PerformAction() { Console.WriteLine("Performing an action..."); OnActionCompleted?.Invoke("Action completed!"); } } public class Program { public static void Main(string[] args) { var example = new EventExample(); example.OnActionCompleted += message => Console.WriteLine(message); example.PerformAction(); } }
-
Task-based Callbacks: With modern asynchronous programming, callbacks are often represented using
Task
andasync/await
.public class AsyncExample { public async Task PerformActionAsync(Func<string, Task> callback) { Console.WriteLine("Performing an action..."); await Task.Delay(1000); // Simulating work await callback("Action completed!"); } } public class Program { public static async Task Main(string[] args) { var example = new AsyncExample(); await example.PerformActionAsync(async message => { Console.WriteLine(message); await Task.CompletedTask; }); } }
Typical Use Cases of Callbacks
-
Asynchronous Programming: Callbacks are often used in asynchronous operations to execute a method after a long-running task (e.g., file I/O, web requests, or database queries) completes.
-
Event Handling: In frameworks like WPF, WinForms, or Unity, callbacks are used to handle user interface events, such as button clicks or mouse movements.
-
Dependency Injection: Callbacks allow injecting custom behavior into a generic method or class without tightly coupling the logic.
-
Extensibility: Callbacks enable creating flexible and reusable APIs, where the library user can supply their custom logic as a callback.
-
Functional Programming: Callbacks can make it easier to perform operations on collections (e.g., LINQ queries) or implement design patterns like strategy and observer patterns.
Callbacks in C# provide a powerful way to decouple components and allow for dynamic behavior in applications.