Yesterday's example showed how to use anonymous methods to apply logic to disparate items. This example was written in C# 2.0. Today I'll demonstrate how to convert this to C# 3.0 and use
lambda expressions instead of anonymous methods.
I'll start with the TestItem class, which can be significantly simplified. The new class is:
public class TestItem
{
public int FirstValue
{ get; set; }
public int SecondValue
{ get; set; }
}
This converts the properties to
automatic properties and loses the constructors as I'll be using the new
object initialisers functionality (if I wanted to enforce construction with particular values I'd supply a custom constructor).
The GetValue delegate may be removed entirely, to be replaced with the .NET Framework supplied
Func delegate. The CalculateSum method gets modified to use this delegate as well as
implicit typing:
private static int CalculateSum<T>(IEnumerable<T> testItems,
Func<T, int> valueGetter)
{
var sum = 0;
foreach (var value in testItems)
{
sum += valueGetter(value);
}
return sum;
}
Finally, the code that invokes the method gets a number of changes. The anonymous methods are replaced with lambda expressions, implict typing is introduced and the TestItem is constructed with object initialisers.
var testItems = new List<TestItem>();
for (var initialValue = 1; initialValue <= 5; initialValue++)
{
testItems.Add(new TestItem { FirstValue = initialValue, SecondValue = initialValue + 1});
}
var firstSum = CalculateSum(testItems, item => item.FirstValue);
var secondSum = CalculateSum(testItems, item => item.SecondValue);
var thirdSum = CalculateSum(testItems, item => item.FirstValue + item.SecondValue);
Console.WriteLine(firstSum);
Console.WriteLine(secondSum);
Console.WriteLine(thirdSum);
So what has this got us? Implicit typing has simplified the various declarations, offloading some work onto the compiler. The TestItem is certainly simpler, as we don't have to declare the fields and were able to drop the constructors. The lambda expressions are simpler to express. So on the whole we've gained some simplicity but haven't really gained any capabilities here that weren't available in C# 2.0.
Our example required us to define a TestItem type to work with. Obviously this was far more work than we wanted to do. What it we try an
anonymous type:
var testItems = new[]
{
new { FirstValue = 1, SecondValue = 2},
new { FirstValue = 2, SecondValue = 3},
new { FirstValue = 3, SecondValue = 4},
new { FirstValue = 4, SecondValue = 5},
new { FirstValue = 5, SecondValue = 6}
};
var firstSum = CalculateSum(testItems, item => item.FirstValue);
var secondSum = CalculateSum(testItems, item => item.SecondValue);
var thirdSum = CalculateSum(testItems, item => item.FirstValue + item.SecondValue);
Console.WriteLine(firstSum);
Console.WriteLine(secondSum);
Console.WriteLine(thirdSum);
This code creates a collection of an anonymous type that is functionally equivalent to the TestItem class (which has no logic of it's own). Due to the limitations of anonymous types we couldn't easily work with them in other methods. The use of lambda expressions here allows us to interact with the type without knowing anything about it.