Some extension methods in Umbrella are simple but yet useful. It usually ends up being exiting methods from the Base Class Library that weren’t defined on the simplest interface required but more as a helper method on more concrete types:
Let’s start with the most straighforward example:
Given:
public class Order
{
public decimal Total { get; set; }
}
We’ll usually see something like:
var orders = new List<Order>();
var order = new Order();
orders.Add(order);
But when the item to add to the collection has a default constructor, we could have a shorter syntax:
var orders = new List<Order>();
var order = orders.AddNew();
But AddNew() isn’t a member of List<T>. Have you guessed how AddNew() is implemented? Using extension methods, of course but what should be extended? List<T>? It is actually ICollection<T> as it is the interface containing the Add method.
public static class CollectionExtensions
{
public static T AddNew<T>(this ICollection<T> items)
where T : new()
{
T item = new T();
items.Add(item);
return item;
}
}
A generic constraint on T having a default constructor is required so that new() can be called.
I mentioned that some helper methods have been defined on concrete types on the past where now, with extension methods, they could be extending simple interfaces. It is the case of List<T>.AddRange():
var orders = new List<Order>();
var newOrders = new List<Order> {
new Order { Total = 100 },
new Order { Total = 150 },
new Order { Total = 200 }};
orders.AddRange(newOrders);
What AddRange logically does, is call Add for each new item. If we were to boil it down to its simplest form:
public static class CollectionExtensions
{
public static void AddRange<T>(
this ICollection<T> collection,
IEnumerable<T> items)
{
items.ForEach(collection.Add);
}
}
Don’t get confused by the “collection.Add” syntax, it is the method group syntax. The equivalent lambda expression would be:
items.ForEach(item => collection.Add(item));
That’s it for Part 2!
() => “Francois”