Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why shouldn't I always use nullable types in C#

I've been searching for some good guidance on this since the concept was introduced in .net 2.0.

Why would I ever want to use non-nullable data types in c#? (A better question is why wouldn't I choose nullable types by default, and only use non-nullable types when that explicitly makes sense.)

Is there a 'significant' performance hit to choosing a nullable data type over its non-nullable peer?

I much prefer to check my values against null instead of Guid.empty, string.empty, DateTime.MinValue,<= 0, etc, and to work with nullable types in general. And the only reason I don't choose nullable types more often is the itchy feeling in the back of my head that makes me feel like it's more than backwards compatibility that forces that extra '?' character to explicitly allow a null value.

Is there anybody out there that always (most always) chooses nullable types rather than non-nullable types?

Thanks for your time,

like image 852
Matthew Vines Avatar asked May 06 '09 16:05

Matthew Vines


People also ask

Should I use nullable reference types?

Although using nullable reference types can introduce its own set of problems, I still think it's beneficial because it helps you find potential bugs and allows you to better express your intent in the code. For new projects, I would recommend you enable the feature and do your best to write code without warnings.

What is the point of nullable reference types?

Nullable reference types are a new feature in C# 8.0. They allow you to spot places where you're unintentionally dereferencing a null value (or not checking it.) You may have seen these types of checks being performed before C# 8.0 in ReSharper's Value and Nullability Analysis checks.

Why do we need nullable in C#?

The Nullable type allows you to assign a null value to a variable. Nullable types introduced in C#2.0 can only work with Value Type, not with Reference Type. The nullable types for Reference Type is introduced later in C# 8.0 in 2019 so that we can explicitly define if a reference type can or can not hold a null value.

What happens when we box or unbox nullable types?

When the nullable type is boxed, the underlying value type is stored in the object, rather than an instance of the nullable type itself. For example, if we box int?, the boxed value will store an int.


2 Answers

The reason why you shouldn't always use nullable types is that sometimes you're able to guarantee that a value will be initialized. And you should try to design your code so that this is the case as often as possible. If there is no way a value can possibly be uninitialized, then there is no reason why null should be a legal value for it. As a very simple example, consider this:

List<int> list = new List<int>() int c = list.Count; 

This is always valid. There is no possible way in which c could be uninitialized. If it was turned into an int?, you would effectively be telling readers of the code "this value might be null. Make sure to check before you use it". But we know that this can never happen, so why not expose this guarantee in the code?

You are absolutely right in cases where a value is optional. If we have a function that may or may not return a string, then return null. Don't return string.Empty(). Don't return "magic values".

But not all values are optional. And making everything optional makes the rest of your code far more complicated (it adds another code path that has to be handled).

If you can specifically guarantee that this value will always be valid, then why throw away this information? That's what you do by making it a nullable type. Now the value may or may not exist, and anyone using the value will have to handle both cases. But you know that only one of these cases is possible in the first place. So do users of your code a favor, and reflect this fact in your code. Any users of your code can then rely on the value being valid, and they only have to handle a single case rather than two.

like image 87
jalf Avatar answered Sep 20 '22 21:09

jalf


Because it's inconvenient to always have to check whether the nullable type is null.

Obviously there are situations where a value is genuinely optional, and in those cases it makes sense to use a nullable type rather than magic numbers etc, but where possible I would try to avoid them.

// nice and simple, this will always work int a = myInt;  // compiler won't let you do this int b = myNullableInt;  // compiler allows these, but causes runtime error if myNullableInt is null int c = (int)myNullableInt; int d = myNullableInt.Value;      // instead you need to do something like these, cumbersome and less readable int e = myNullableInt ?? defaultValue; int f = myNullableInt.HasValue ? myNullableInt : GetValueFromSomewhere(); 
like image 23
LukeH Avatar answered Sep 20 '22 21:09

LukeH