Dev Tips - Dealing with nullables

Reading time ~4 minutes

Random discussions about nullables


Dealing with nullable types in C# is a very common scenario one encounters as a developer. It’s especially common when dealing with data extracted from a database or de-serializing data from JSON

There are various methods that a developer can use to tackle these scenarios, but the progression is usually mirrored below.

A basic approach for dealing with nullabe types will often look something like this:

class NullableExample
{
	static void Main()
	{
		int? num = null;

		// Is the HasValue property true? 
		if (num.HasValue)
		{
			System.Console.WriteLine("num = " + num.Value);
		}
		else
		{
			System.Console.WriteLine("num = Null");
		}

		// y is set to zero 
		int y = num.GetValueOrDefault();

		// num.Value throws an InvalidOperationException if num.HasValue is false 
		try
		{
			y = num.Value;
		}
		catch (System.InvalidOperationException e)
		{
			System.Console.WriteLine(e.Message);
		}
	}
}

The code above (taken directly from msdn) shows the basic usage of a nullable type. The section below demonstrates how to create the nullable type, then checked if it is assigned and finally to act accordingly.

    int? num = null;

    // Is the HasValue property true? 
    if (num.HasValue)
    {
        System.Console.WriteLine("num = " + num.Value);
    }
    else
    {
        System.Console.WriteLine("num = Null");
    }

While this code works it could be a bit cleaner:

int? num = null;
string testString = "We have " + num ?? 0 + " Sheep";

The code above introduces a new (new as in new to this example , the operator has been around for ages) operator called the coalescing operator. As we can see in the example above, the coalescing operator vastly simplifies the checking of a nullable type and then using an alternate value if the value is null.

While that is useful it doesnt allow for implicit casting without having to wrap everything in braces. So instead we can use the GetValueOrDefault function.

GetValueOrDefault is an instance method on all nullable types which will return the value that was set for the nullable object or a default value if it is null. Because we are dealing with a single value returned from the function, .net is able to implicity cast most values without any extra work needed from our side. Before going any further I wanted to have a look at the source code of this function to see if it was doing anything special. As expected it works exactly as I expected it to.

public T GetValueOrDefault(T defaultValue) {
	return HasValue ? value : defaultValue;
}

As in our original example, it simply checks if we have a value then returns that value or returns a default value that we can pass in.

Lastly an example of using this function with implicit casting for string concatanation can be seen below.

int? test = null
string testString = "We have " + test ?? 0 + " Sheep";
(1,14): error CS0019: Operator '??' cannot be applied to operands of type 'string' and 'int'

As expected that was not going to work without more brackets in place to fix the ordering, so to get it working we would need to write it as follows.

int? test = null
string testString = "We have " + (test ?? 0) + " Sheep";

As expected because we are applying the correct ordering, the ?? operator can now correctly get the value we want and cast it to a string implicitly.

To make this work with the GetValueOrDefault is just as easy, if not simpler.

int? test = null
string testString = "We have " + test.GetValueOrDefault() + " Sheep";

The example above shows how the method could be used and also demonstrates the functions ability to return the correct default value if we do not pass one in. In the example above the string will print “We have 0 Sheep” which is what we expect. We could also pass in our own default value to the function as needed.

int? test = null
string testString = "We have " + test.GetValueOrDefault(-1) + " Sheep";

This example above would print “We have -1 Sheep”, (while not really physically possible) it just demonstrates how one could seed the default value for an object type with what ever they want.

In the end all these methods perform the same job and really it just comes down to personal preference about which method you use. The biggest benefit to using the GetValueOrDefault seems to be when working with strings, as you dont need to worry about nesting of brackets. The function is also useful if you do not know what the default value should be for a specific type as the function will return the correct object types default for you.

For further examples on how the function is used have a look at the Newtonsoft.JSON library as well the internals of the microsoft clr (IEnumerable uses it for summing).

Embracing the ultra

# IntroThis past month marked the latest iteration of the 360one MTB and the culmination of months of training. In the end, it wasn't jus...… Continue reading

Cyber Apocalypse 2021 CTF

Published on April 24, 2021

Covert Login Alerting

Published on June 01, 2020