Design a site like this with WordPress.com
Get started

Pragmatic Null

I’m still working to embrace strict null in C#. In the mean time here are a few notes on how I try to deal with null today.

Avoid null as a sentinel value. Sentinel values are really just a specific example of the more general “magic number” anti-pattern. Magic numbers are bad enough in general. At least a magic number like -1 doesn’t tend to accidentally appear. However, magic values like 0 and null are easily set accidentally.

If you really need to communicate something complicated back to the caller, then return a data structure with better semantics. Languages like Python and Go make this easy because their functions can return multiple values or use tuple unpacking. C# doesn’t have those features, so you will need to define a class or struct to hold the values you need to explain to the caller. Still it is better than using magic numbers to communicate.

Specifically for lists, dictionaries, and other data structures, returning an empty structure is often better than returning null. Functions can often be chained together in pipelines, and some of the functions in the pipeline might not accept null. Usually, they will happily accept empty data structures.

A null value is usually more obviously “blank” than an empty string. Unless an empty zero length string actually has semantic meaning to your context, it’s probably best to just return null.

Accept null values whenever possible. This is a more specific case of Postel’s Law: be liberal in what you accept, and conservative in what you send. If somebody passes in null, treat that as an empty value, as far as you can. Try not to throw an exception.

Certainly, if a null value is an error in your context, then by all means throw an exception.

In C# you can quickly turn a null value into a reasonable default by using the ?? operator.

If null or empty is a reasonable value for your semantics, then go ahead and return it. For example if you have a search function, and the caller searches for something that doesn’t match anything, then returning null is fine. Especially if they pass in null, then return null. SQL makes good use of this principle with its “three-valued logic”. Propagating null through the system, rather than throwing exceptions, can often make the most sense.

Advertisement
%d bloggers like this: