In the project I am currently working on we use a domain model with a quite deep nested structure of classes, code like the following is quite common.
// do something with the Adress
Console.Writeline(Contract.Parties.Client.Adress.Street);
The problem with this is that not all Contacts have a related Parties object and if we do have a Parties object sometimes the Client object is Null. This lead to writing a lot of code code like the following:
if (Conract != Null &&
Contract.Parties != null &&
Contract.Parties.Client != null &&
Contract.Parties.Client.Adress != null)
{
// do something with the Adress
Console.Writeline(Contract.Parties.Client.Adress.Street);
}
There are a few problems with this code, the first of which is that it is quit verbose. Second it evaluates the same properties over and over again. In order to reduce the double work we could introduce some extra local variables and create a separete if statement for every step, this will make it even more verbose than it is allready.
Of course C# 3.0 has a lot of new syntax tricks, like extension methods, lambda expression and type inference. I had seen some nice examples (mostly Linq related) but had not been using these features to the max myself. Somehow I got the idea that these features would help me solve the Null checking problem.
I figured that the code I wanted to write was something like the following.
if (Contract
.NullSafe(c => c.Parties)
.NullSafe(p => p.Client)
.NullSafe(c => c.Address) != null)
{
// do something with the adress
Console.Writeline(Contract.Parties.Client.Adress.Street);
}
The idea is that all parts of the path are expressed in separate lambda expressions which are chained together. If any link in the chain returns null, the rest of the path is never evaluated and the result of the whole expression will also be null.
All I had to do to make this possible was write one single extension method that would operate on any object, I was quite amazed that I could do this with verry little code that, besides some generic stuff, was actually quite simple.
public static TResult NullSafe<T, TResult>(this T target, Func<T, TResult> func)
{
if (target != null)
return func(target);
else
return default(TResult);
}
All the generics make it look a lot more complicated than it actually is. This extension method receives two arguments, the first of which is the object it operates on and the second is a generic Func<T, TResult> delegate (the lambda expression). The return type of the extension method is automatically inferred from the return type of the lambda that is passed in. This allows you to call NullSafe again on the result of the first call and use IntelliSense to type p.Client in the second lambda.
The nice thing about extension methods is, besides that they can operate on any existing class without changing it, that they can also operate on Null references without causing a NullReferenceException!! This makes it possible to test for null inside the extension method. If the object it is called on is not null it evaluates the lambda expression and returns the result. Otherwise it returns the default value of the expected return type, for reference types this is Null.
To make life even better I created another overload of NullSafe that was even simpler
public static void NullSafe<T>(this T target, Action<T> action)
{
if (target != null)
action(target);
}
Instead of a generic Func<T, TResult> delegate this one receives a Generic Action<T> delegate and returns void.
This removes the need to retype the whole path inside the if, it actually removes the if altogether.
Contract
.NullSafe(c => c.Parties)
.NullSafe(p => p.Client)
.NullSafe(c => c.Address)
.NullSafe(a =>
{
// do something with the adress
Console.Writeline(a.Street);
});
To bad for me, my current project is still on C# 2.0 so I'll keep doing it old school style 🙁
Exercise
If you would also like some practice with C# 3.0, I would like challenge you to write something that allows me to do the same thing for IEnumerable<T>, I would like to write something like the following
foreach (Order order in Contract
.NullSafe(c => c.Parties)
.NullSafe(p => p.Client)
.NullSafe(c => c.Orders)
{
// do something with order
Console.Writeline(o.Amount);
}
Where Client.Orders is of type IEnumerable<Order>. The idea is that I want to iterate every Order in Contract.Parties.Client.Orders. If at any stage in the path (including the Orders collection) we encounter a Null reference we will just loop an empty enumerator and do nothing.
4 comments
Hey Frank,
isn’t the problem that you introduce high coupling in your classes. Your problem isn’t the null tests, it is that the caller of contract now is tied to the Parties, Client and Address classes.
I think you should rewrite to:
if (Contract != null)
{
string street = Contract.GetClientStreet();
Console.Writeline(street);
}
and then handle the rest of the code inside the Contract, and Parties classes.
I always try to avoid calling a member of a member. Something with the ‘law of demeter’ http://en.wikipedia.org/wiki/Law_of_Demeter
Wouter
Contract.Parties.Client.Adress.Street
According to most best practices this just isn’t the right way to do it.
The problem is that the current code knows way too much about the internal structure of the classes. You might consider adding methods to the classes so you could write something like the following instead:
Contract.PrintClientAddress();
ernow
Erno made the point I was afraid that would come up, I believe the pragmatic programmers call it ‘Don’t talk to strangers’. I think this is a good principle that should be honered whenever possible.
The problem is that in a lot of situations this is just no practical (as is admitted by the same pragmatic programmers). In the project I was taking about the domain model are actually data transfer objects. As they are pure Data transfer objects the do not contain any logic, but are merely generated from an XSD (as is common practice for WCF or ASMX services)
A common situation where I find myself reaching down a deep dark path into a datastructure is in validating business constraints on input messages. A common practice is to let every validation rule operate on the whole input message, and then let the validation rule it self eveluate whatever data is relevant. This way only the code of the business rule itself knows what exact data it operates on and this knowledge doesn’t get scatterd around.
One could argue that this is not really OO and I think that is actually true. Service Oriented Architecture and OO are not in all situations best friends.
frankb
Partial classes could counter your argument there. As you generate your data transfer objects from xsd’s you could add business logic to them by using partial classes. Then everything Erno said makes sense again. The pragmatic programmers, at least the book, is from the pre partial class area 😉
guidol