In the previous installment of this series, we saw why the null value can be an annoying source of errors. But there are cases when you positively wish for a variable, that otherwise cannot be null, to be able to have a null value. Imagine, for example, a web site that stores the last time each user has logged in.
public class User { public string NickName { get; set; } public string Email { get; set; } public string PasswordHash { get; set; } public DateTime LastLoginTime { get; set; } } If a user has just registered but they haven’t yet logged in, we want the LastLoginTime property to be somehow empty.
I really like nullable types, they can be very effective for writing safer code.
Sometimes there are good reasons to separate object construction and initialization (e.g. composite / loosely coupled objects, or encapsulation of 3rd party libraries) so there can be properties/fields that do not yet have valid values, and using separate queries for this is error prone.
I write a lot of communication interfaces for sensors/actuators and if the communication drops, nullables are a good way to represent invalid readings.
Being able to convey the value and validity in one variable can be more thread-safe and easier to write pure-functions, and show intent.
I occasionally use a nullable for singleton patterns if I’m not 100% convinced there can never be multiple instances, rather than painting myself into a corner with a static class. e.g.
public static MyClass Instance => _instance ??= new(); private static MyClass? _instance;
Those who are trying to avoid milk should consider using
Lazy<MyClass> _instance;