Introduction
There are many times that I've been asked about delegates and lambda expressions, specifically on the practical use or implementation of them. One of the more important aspects of these features is creating code that provides parallel, if not improved, levels of functionality with less repetition and bloat. One of the best practices in object-oriented programming is the idea of refactoring, which is reorganizing code into a more modular form based on the frequency and use.
Using the Code
So here's a quick example of code that performs some operations on a list of numbers:
class Program
{
static void Main(string[] args)
{
List<int> numbers = new List<int> { 2, 4, 6, 8, 10 };
foreach (int num in numbers) {
Console.WriteLine("{0} x 2 = {1}", num, num * 2);
}
numbers.Clear();
numbers.AddRange(new int[] { 1, 3, 5, 7, 9 };
foreach (int num in numbers) {
Console.WriteLine("{0} x 2 = {1}", num, num * 2);
}
}
}
Public Class Program
Public Shared Sub Main(ByVal args() As String)
Dim numbers As List(Of Integer) = New List(Of Integer) From { 2, 4, 6, 8, 10 }
For Each num In numbers
Console.Writeline("{0} x 2 = {1}", num, num * 2)
Next
numbers.Clear()
numbers.AddRange({ 1, 3, 5, 7, 9 })
For Each num In numbers
Console.Writeline("{0} x 2 = {1}", num, num * 2)
Next
End Sub
End Class
We create a list of integers, iterate through the list showing each value and the result of the value multiplied by two, clear and repopulate the list, and perform the same iteration. While this code is valid, and probably commonly seen, it can be reorganized and reduced using delegates. Let's take a look at this code with some revisions:
class Program
{
static void Main(string[] args)
{
List<int> numbers = new List<int> { 2, 4, 6, 8, 10 };
Action<int> writeMultipliedValue = (num => Console.WriteLine("{0} x 2 = {1}", num, num * 2));
numbers.ForEach(writeMultipliedValue);
numbers.Clear();
numbers.AddRange(new int[] { 1, 3, 5, 7, 9 };
numbers.ForEach(writeMultipliedValue);
}
}
Public Class Program
Public Shared Sub Main(ByVal args() As String)
Dim writeMultipliedValues As Action(Of Integer) = _
Sub(num) Console.WriteLine("{0} x 2 = {1}", num, num * 2)
Dim numbers As List(Of Integer) = New List(Of Integer) From { 2, 4, 6, 8, 10 }
numbers.ForEach(writeMultipliedValues)
numbers.Clear()
numbers.AddRange({ 1, 3, 5, 7, 9 })
numbers.ForEach(writeMultipliedValues)
End Sub
End Class
A point to note is the declaration of the Action(T) delegate which is assigned the value of a lambda expression. The lambda expression contains the display code that was in the foreach
loop in the previous example. Since we know that both of the foreach
loops performed the same task, it stands to reason that this code could be placed in a separate method and called as needed.
The List(T) class provides a method, ForEach, which performs an action on each element contained therein, which accepts an Action(T) instance for its only parameter. We then use the Action(T) delegate we assigned as the value supplied to the parameter of the ForEach method, in effect creating the same functionality as our foreach
loops in the previous example.
Using delegates in this manner is a great way to keep your code short, sweet, and to the point. If you're not familiar with delegates, lambda expressions, or the DRY principle, I'd recommend reading up on these topics: