Let's say I have a class Person with your typical field/properties FirstName, LastName, blah, blah... Then let's say I decide to implement the Null Object Pattern. Why I decide this isn't important right now, but I know that I am just going to initialize all my fields to default setttings (string.Empty for FirstName,LastName, etc..) in the constructor. Like so:
public class NullPerson : Person, INull
{
public NullPerson() : base(string.Empty,string.Empty,string.Empty,null)
{
}
}
Now, notice I have a marker interface called INull. In my code later on I might have something like :
if( person==null || person is INull )
// do something
This kind of code flags me to consider using Specification to encapsulate these kinds of checks. So in a project that is Common to all in my solution, I write this simple little object:
public class NonNullSpecification<T> where T : class
{
public bool IsSatisfiedBy(T item)
{
return item != null && !(item is INull);
}
}
I'm include the T:class in my where clause to prevent the use of this spec on ValueType derivatives.
This is implementing a variation on a slick generic Specification that Jean-Paul Boodhoo demonstrated and is implementing the pattern that is discussed deeper in Eric Evans' Domain Driven Design book.
public interface ISpecification<T>
{
bool IsSatisfiedBy(T item);
}
Now to use in my code I can just use this to check for nulls in a consistent way across my app
return new NonNullObjectSpecification<Person>().IsSatisfiedBy(e.Person);
I admit this is an edge-case example...doing this may not be justified. But I love encapsulating these tiny rules that span my application so that if they change for whatever reason, I can go to one place to change them. I know checking for null isn't prone to change, but think of how many times you had to go finding code that implemented a rule and make those changes manually (ReSharper would help alot, too I know). The point is, when I see myself doing checks on things more than once, I try to ask whether this is a Specification that i haven't identified yet and see if I can wrap those rules into a consistent interface.