I’ve found this question while going over my old StackOverflow answers:
I’m using reflection to loop through a Type’s properties and set certain types to their default. Now, I could do a switch on the type and set the default(Type) explicitly, but I’d rather do it in one line. Is there a programmatic equivalent of default?
I encourage you to read till the end before checking my answer – because I want to show you how this task can be solved using TDD (Test Driven Design).
[From Wikipedia]
Test #1 – handle null input
Let’s write the first test – when null is passed return null:
[Test]
public void GetDefault_PassNull_ReturnNull()
{
var result = DefaultCreator.GetDefault(null);
Assert.That(result, Is.Null);
}
Now all we need is to make the test pass and so implementing this requirement is as simple as can be:
public class DefaultCreator
{
public static object GetDefault(Type type);
{
return null;
}
}
Although this seems like cheating this is the way to create the design piece but piece, instead of creating it all upfront I hope that things would get clearer in the process just keep in mind that the worse case scenario is that we have a test that checks what happens if null is passed.
Test #2 – reference types
Next test – if T is an object default(T) will return null:
[Test]
public void GetDefault_PassObject_ReturnNull()
{
var result = DefaultCreator.GetDefault(typeof(object));
Assert.That(result, Is.Null);
}
Running the test shows a cool feature of test driven design – the test passes! and so right now we have a class that satisfies two out of three of our requirements.
Test #3 – primitives
All we need to implement now is how to behave when a value type is passed – and so we write another test:
[Test]
public void GetDefault_PassInteger_Return0()
{
var result = DefaultCreator.GetDefault(typeof(int));
Assert.That(result, Is.EqualTo(0));
}
And write the simplest solution that makes it pass:
public class DefaultCreator
{
public static object GetDefault(Type type)
{
if (type == typeof(int))
{
return 0;
}
return null;
}
}
So far so good but we’re not done yet – after writing a few more tests for double, float and long refactoring brought this solution:
public class DefaultCreator
{
public static object GetDefault(Type type)
{
if (type.IsPrimitive)
{
return 0;
}
return null;
}
}
Test #4 – Structs
Still with me good – what about a complex value type :
[Test]
public void GetDefault_PassStruct_ReturnEmptyStruct()
{
var result = DefaultCreator.GetDefault(typeof(MyStruct));
Assert.That(result, Is.TypeOf());
}
Now that we have a failing test – we can add functionality to fix it:
public class DefaultCreator
{
public static object GetDefault(Type type)
{
if (type.IsValueType)
{
return Activator.CreateInstance(type);
}
return null;
}
}
Run all of the tests and that’s it – we have a class that mimics default(T) at run-time one step at a time.
The end
Of course I could have created this class without unit tests but I wanted to show a simple (but not too simple) example that shows how to use unit tests as a design tool.
Happy coding…
Although TDD is not that simple the example shown here is a very good demonstation of how helpful can be. TDD is a very disciplined practice that requires excellent knowledge of unit testing and the domain of the system under development. In any case congratulations for the case described here 🙂