Example 1 - Multiple event handlers for an event
You can assign multiple event handler to an event.
The following example shows how you can assign multiple event handlers to an event:
using System;
namespace ConsoleApp1
{
class Program
{
static void Main(string[] args)
{
var timer = new System.Timers.Timer();
timer.Elapsed += Timer_Elapsed1;
timer.Elapsed += Timer_Elapsed2;
timer.Interval = 1000;
timer.Start();
Console.ReadLine();
timer.Stop();
timer.Dispose();
}
private static void Timer_Elapsed1(object sender, System.Timers.ElapsedEventArgs e)
{
Console.WriteLine("Elapsed 1");
}
private static void Timer_Elapsed2(object sender, System.Timers.ElapsedEventArgs e)
{
Console.WriteLine("Elapsed 2");
}
}
}
You can use either of the following syntaxes for the event handlers:
timer.Elapsed += Timer_Elapsed1
Or
timer.Elapsed += new ElapsedEventHandler(Timer_Elapsed1)
Where Timer_Elapsed1 is a method like this:
private static void Timer_Elapsed1(object sender, System.Timers.ElapsedEventArgs e)
{
/* code */
}
Or
timer.Elapsed += delegate (object sender, System.Timers.ElapsedEventArgs e) {
/* code */
};
Or
imer.Elapsed += (sender, e) => {
/* code */
};
To learn more about event handling take a look at:
Example 2 - Using AsyncCallback in APM
The following example shows how you can use an AsyncCallBack in Asynchronous Programming Model (APM) pattern. It basically is passing a delegate to a method as a parameter:
using System;
using System.IO;
namespace ConsoleApp1
{
class Program
{
static Stream fs;
static void Main(string[] args)
{
var file = new System.IO.FileInfo(@"c:\temp\Clean-CMClientCache.log");
var buffer = new byte[file.Length];
fs = new FileStream(file.FullName, FileMode.Open, FileAccess.Read,
FileShare.Read, 500, FileOptions.Asynchronous);
Console.WriteLine("Loading file ...");
fs.BeginRead(buffer, 0, buffer.Length, MyAsyncCallBack, null);
Console.ReadLine();
}
private static void MyAsyncCallBack(IAsyncResult ar)
{
Console.WriteLine("Load file completed.");
var bytes = fs.EndRead(ar);
Console.WriteLine($"The file is {bytes} Bytes");
fs.Close();
fs.Dispose();
}
}
}
You can learn more:
- Asynchronous programming patterns
- Asynchronous Programming Model (APM)
- Using an AsyncCallback Delegate to End an Asynchronous Operation
Example 3 - Decoupling and Generic behavior
You can use delegates to inject different behavior, and decouple your classes/methods from implementation details. The same way that you can inject an interface in a class constructor, you can inject a delegate. It basically means you can pass any method which can implement the signature of the delegate, which means you can inject different behavior based on the same contract.
Every time that you are passing a delegate to a method, property or constructor, you are doing this; for example all IEnumerable extension methods are doing this.
In the following example, I've implemented a Filter method which accepts a delegate as a condition; so I can filter a list, based on any condition; The condition could be any method which accepts an element and just return true, if it should be included in the result:
using System;
using System.Collections.Generic;
namespace ConsoleApp1
{
delegate bool Condition<T>(T input);
static class Extensions
{
public static IEnumerable<T> Filter<T>(this IEnumerable<T> input, Condition<T> condition)
{
foreach (var item in input)
{
if (condition(item))
yield return item;
}
}
}
class Program
{
static void Main(string[] args)
{
var numbers = new[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
Console.WriteLine("Even numbers:");
var even = numbers.Filter(delegate (int x) { return x % 2 == 0; });
// Or simply:
//var even = numbers.Filter(x => x % 2 == 0);
foreach (var item in even)
{
Console.WriteLine(item);
}
Console.WriteLine("Odd numbers:");
var odd = numbers.Filter(delegate (int x) { return x % 2 == 1; });
foreach (var item in odd)
{
Console.WriteLine(item);
}
Console.ReadLine();
}
}
}
Example 4 - Invoke delegate
Delegate is a type which encapsulates a method; it's something like method a pointer and you can invoke the delegates the same way that you invoke methods, assuming you have a method having the signature void Method1()
in a delegate variable, like m
, then you can invoke it simply like: m();
.
Here is an example, where we have created a delegate to say hello in a language, and provided two implementations-basically two methods, and later invoked the two delegates:
using System;
namespace ConsoleApp1
{
delegate string Hi(string name);
class Program
{
static string HiInEnglish(string name) { return $"Hi {name}!"; }
static string HiInDanish(string name) { return $"Hej {name}!"; }
static void Main(string[] args)
{
var hi1 = new Hi(HiInEnglish);
var hi2 = new Hi(HiInDanish);
var str1 = hi1("John");
var str2 = hi2("John");
Console.WriteLine(str1);
Console.WriteLine(str2);
Console.ReadLine();
}
}
}
Example 5 - Delegates in Linq
Delegates are heavily used in Linq extension methods in Enumerable class. Look at the following example:
using System;
using System.Linq;
namespace ConsoleApp1
{
class Program
{
static void Main(string[] args)
{
var numbers = new[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
var odd = numbers.Where(x => x % 2 == 1);
odd.ToList().ForEach(x => { Console.WriteLine(x); });
Console.ReadLine();
}
}
}
In above example, x => x % 2 == 1
is an Expression<TDelegate> and x => { Console.WriteLine(x); }
is an Action<T>.