Showing posts with label Action. Show all posts
Showing posts with label Action. Show all posts

Thursday, April 9, 2015

Adding Action to your .Add

I've learned not to be intimidated by C#'s rich library for delegate and lambda operations.  In fact, I've come to embrace Func and Action as tools to simplify APIs and keep my code clean.  One pattern I really liked when I first saw it, and try to encourage its use, is offering an override along the lines of .Add<T>(Action<T> aNewT) any time an API exposes the ability to add something to a collection.

The vendors of server-side web controls all use this pattern for adding columns to a grid control. First consider the delegate-less approach:

GridColumn myColumn = new GridColumn();
myColumn.Title = "Name";
myColumn.Sortable = true;
myColumn.Filterable = true;
etc...

mySuperGrid.Columns.Add(myColumn);

Maybe we can clean things up a little by declaring the new anonymous object within .Add method call:

mySuperGrid.Columns.Add(new GridColumn() 
{
      Title = "Name";
       etc...
});
But most of the time, won't I always want to add a new object?  So why make me bother to type "new"?  And if I can only add GridColumn types, why make me type that too?  So consider the following override for the .Add method:

public void Add(Action<GridColumn> initializerDelegate)
{
       GridColumn newColumn = new GridColumn();
       //We could even do some default intialization if it wasn't already done in GridColumn's 
       //constructor...
       newColumn.myProperty=myDefaultValue;
       
       initializerDelegate(newColumn);

       myColumnCollection.Add(newColumn);
}

Now look what a consumer of the API can do:

mySuperGrid.Columns.Add(column=>
{
      column.Title="Name";
      column.Sortable=true;
      etc..
});

In my opinion, this is much cleaner and simpler for consumers of the .Add method.  Note the consumer doesn't have to know the name of the type used to represent a new column, nor worry about correctly instantiating a new instance of one. Compile-time binding and Intellisense still apply!

So don't fear "=>", it really is your friend!