The introduction of LINQ and functional paradigms in .NET brings new ways of thinking and coding to the mainstream. They also create alternate ways to do mundane coding constructs and this raises the question; which is the right way? For example, this code is copying all the properties from a Data Transfer Object into another, a handmade clone for illustration purposes (obj is of type Settings and is assumed to be created elsewhere):
var s = session.Get(settingId);
foreach (var prop in s.GetType().GetProperties())
{
if (prop.CanWrite)
obj.GetType()
.GetProperty(prop.Name)
.SetValue(obj, prop.GetValue(s, null), null);
}
This is simple enough, let’s raise the coolness factor and introduce some LINQ:
var s = session.Get(settingId);
foreach (var prop in
from p in typeof(Settings).GetProperties()
where p.CanWrite select p)
{
obj.GetType()
.GetProperty(prop.Name)
.SetValue(obj, prop.GetValue(s, null), null);
}
I am sure there are other ways of doing this but let’s concentrate on these two examples. Both do the same thing; the question is which is more readable and maintainable?
The first option is classic C# code accessible to anyone with a .NET or Java background. The filtering rules are separated from the iteration construct making them stand out in the code. Both the intent of the loop and the action in its body are clear. The LINQ option mixes the iteration and filtering code relegating the filter to the end of that line of code. In the example I use whitespace to make it stand out but I guess that many programmers would use a single line of code. Even so, whitespace is a valid tool and the intent of the whole operation is expressed in a concise manner. If the filter was more complex then this option would probably “scale” better.
But now, we blow the coolness factor over the roof and add a taste of fluency:
var s = session.Get(settingId);
(from p in typeof(Settings).GetProperties() where p.CanWrite select p)
.ToList()
.ForEach(x => obj.GetType()
.GetProperty(x.Name)
.SetValue(obj, x.GetValue(s, null), null));
This code is exactly the same as the previous two examples but it is a complete departure from what most developers are used to. I would argue that this coding style is less maintainable than the previous examples because it significantly raises the bar in terms of the language features the developer must know. I also feel that, despite the coolness factor, the intent of the operation is not as clear as in the two previous code snippets.