Code Housekeeping - Part 4 - Avoid NULL Wherever Possible
[C#, Languages, CodeHouseKeeping, Code, Quality]
This is Part 4 of the CodeHousekeeping Series.
Code Housekeeping refers to general rules of thumb that make code easier to read, digest, and modify for other developers, yourself included.
In an ideal world, we would always have all the data for the properties of our types.
Take this simple example:
public record Person
{
public string FirstName { get; set; }
public string LastName { get; set; }
public Gender Gender { get; set; }
}
We can see here a property Gender, that is an Enum;
public enum Gender
{
Male,
Female
}
We would use it like this:
using Serilog;
Log.Logger = new LoggerConfiguration().WriteTo.Console().CreateLogger();
var james = new Person()
{
FirstName = "James",
LastName = "Bond",
Gender = Gender.Male,
};
Log.Information("Welcome {FirstName} {LastName}", james.FirstName, james.LastName);
However, what if there is a situation where you don’t know the Gender?
One way to go about this is as follows:
var other = new Person()
{
FirstName = "Great",
LastName = "Scott",
Gender = null,
};
To get this to work, you must change the Person to make Gender nullable.
public record Person
{
public required string FirstName { get; init; }
public required string LastName { get; init; }
public required Gender? Gender { get; init; }
}
This works, but presents a number of issues:
- Your logic must factor in
Male,FemaleandNULL - You have to keep checking whether
GenderisNULLbefore using it
A better solution is to introduce an actual value to represent unknown, like this:
public enum Gender
{
Male,
Female,
Unknown
}
This allows us to do the following:
var unknown = new Person()
{
FirstName = "Jane",
LastName = "Bond",
Gender = Gender.Unknown,
};
This is much cleaner, and explicit.
It also allows us to write logic like this:
public sealed record Person
{
public required string FirstName { get; init; }
public required string LastName { get; init; }
public required Genders? Gender { get; init; }
public string Salutation => Gender switch
{
Genders.Male => "Mr",
Genders.Female => "Mrs/Miss",
Genders.Unknown => "Other",
_ => "Fellow Kenyan"
};
}
The Salutation logic here uses switch expressions that ensures the compiler enforces all the paths.
However, there are situations where NULL is unavoidable.
Take this updated Person:
var bourne = new Person()
{
FirstName = "Jason",
LastName = "Bourne",
Gender = Genders.Male,
DateOfBirth = null
};
In this case, a default DateOfBirth makes no sense if we did not know it at the point of data entry.
In such scenarios, a NULL is unavoidable.
TLDR
Avoid NULL values whenever possible.
The code is in my GitHub.
Happy hacking!