Delegates as callback pattern in C Sharp (C#) - Time & Space Complexity
When using delegates as callbacks, it is important to understand how the program's running time changes as the input grows.
We want to know how many times the callback runs and how that affects overall execution time.
Analyze the time complexity of the following code snippet.
public delegate void Callback(int value);
public void ProcessItems(int[] items, Callback callback)
{
foreach (var item in items)
{
callback(item);
}
}
This code runs a callback delegate on each item in an array.
Identify the loops, recursion, array traversals that repeat.
- Primary operation: The foreach loop that calls the callback for each item.
- How many times: Once for every element in the input array.
As the number of items grows, the callback runs more times, directly increasing total work.
| Input Size (n) | Approx. Operations |
|---|---|
| 10 | 10 callback calls |
| 100 | 100 callback calls |
| 1000 | 1000 callback calls |
Pattern observation: The work grows in a straight line with input size.
Time Complexity: O(n)
This means the time to run grows directly in proportion to the number of items.
[X] Wrong: "The callback runs only once, so time is constant regardless of input size."
[OK] Correct: The callback runs once for each item, so more items mean more calls and more time.
Understanding how callbacks affect time helps you explain how your code scales and shows you can reason about program efficiency.
"What if the callback itself contains a loop over the entire array? How would the time complexity change?"
Practice
Solution
Step 1: Understand delegate usage
Delegates allow methods to be passed as parameters to other methods.Step 2: Identify callback purpose
This passing enables callbacks, which run code after some work is done.Final Answer:
To pass methods as parameters and execute them later -> Option CQuick Check:
Delegates = method parameters for callbacks [OK]
- Confusing delegates with classes
- Thinking delegates handle exceptions
- Assuming delegates convert data types
Solution
Step 1: Recall delegate declaration syntax
The correct syntax is: delegate returnType DelegateName(parameterList);Step 2: Match syntax to options
delegate void MyDelegate(int number); matches this pattern: delegate void MyDelegate(int number);Final Answer:
delegate void MyDelegate(int number); -> Option DQuick Check:
delegate returnType Name(params) = delegate void MyDelegate(int number); [OK]
- Placing 'void' before 'delegate'
- Swapping delegate and return type order
- Misplacing delegate keyword after name
delegate void Callback(string message);
class Program {
static void Main() {
Callback cb = msg => Console.WriteLine($"Hello, {msg}!");
RunProcess(cb);
}
static void RunProcess(Callback callback) {
Console.WriteLine("Starting process...");
callback("World");
Console.WriteLine("Process finished.");
}
}Solution
Step 1: Trace method calls in Main and RunProcess
Main creates a callback that prints "Hello, {msg}!" and passes it to RunProcess. RunProcess prints "Starting process...", calls callback with "World", then prints "Process finished.".Step 2: Determine output order
Output lines are: "Starting process...", "Hello, World!", "Process finished." in that order.Final Answer:
Starting process... Hello, World! Process finished. -> Option AQuick Check:
Callback runs between start and finish prints [OK]
- Assuming callback runs before 'Starting process...'
- Mixing output order
- Ignoring lambda execution timing
delegate void Notify();
class Test {
static void Main() {
Notify n = NotifyMethod;
Run(n);
}
static void Run(Notify callback) {
callback();
}
static void NotifyMethod(string message) {
Console.WriteLine(message);
}
}Solution
Step 1: Compare delegate and method signatures
Delegate Notify expects a method with no parameters and void return. NotifyMethod takes a string parameter, so signatures differ.Step 2: Understand delegate assignment rules
Assigning NotifyMethod to Notify delegate causes a compile-time error due to signature mismatch.Final Answer:
Delegate signature does not match method signature -> Option BQuick Check:
Delegate and method signatures must match [OK]
- Ignoring parameter mismatch
- Thinking delegate instantiation is wrong
- Assuming missing return causes error here
ProcessData that takes an integer array and a delegate callback to process each element asynchronously. Which approach correctly uses delegates as callbacks to print each element after processing?Solution
Step 1: Identify delegate type for element processing
Since each element is an int and we want to process it,Action<int>fits as it takes int and returns void.Step 2: Use asynchronous calls inside loop
CallingTask.Run(() => callback(item))runs the callback asynchronously for each element.Final Answer:
Define a delegateAction<int>and call it inside a loop withTask.Run(() => callback(item))-> Option AQuick Check:
Delegate matches parameter and async call runs callback per item [OK]
- Using delegate with wrong parameters
- Calling callback only once instead of per item
- Ignoring async execution
Ready to prove it?
Pass the test and this pattern moves unknown
