Nullable Types
It specialist's tricks
Описание
Nullable types - тип переменных, задача которых упростить работу с примитивными типами, в случаях, когда значение переменной настолько неясно, что даже default значение не подходит для определения значения переменной.
Nullable типы можно объявить несколькими способами:

Варианты использования:
1. Сравнение с целочисленным не Nullable примитивом, совпадающим с примитивом Nullable типа.
2. Сравнение с null.
3. Сравнение с другими Nullable типами одного примитива.

Вывод:

Особенности:
Value type или Reference type
На самом деле здесь нет развернутого ответа. Nullable Types - это Value type.
Единственное, что стоит отметить, в C# 8 были введены Nullable reference types, которые как-раз являются Reference type, но они применяются только к существующим Reference types, такие как string, object.
Также введенные Nullable reference types и синтаксис C# 8 ломают Records, позволяя обходить введенные ограничения компилятора для Records, с помощью !, но это уже совсем другая история.
Boxing allocation
Первый случай, когда мы упаковываем переменные с одинаковым значением.

При упаковке, так как переменные Value type, мы рассчитываем, что ссылки на эти значения будут разные, так как они находятся в разных областях памяти.
Вывод:

Что, собственно, мы и видим при выполнении программы.
Второй случай, когда мы упаковываем переменные с одинаковым значением, но на этот раз одинаковое значение будет null.

Казалось бы, та же самая ситуация, два Value type, ссылаются на разные участки памяти, пусть и с пустым значением, при упаковке должны ссылаться на разные участки памяти.
Вывод:

Ага! Тут то и оно. CLR (возможно JIT) считает: "зачем две ссылочные переменные должны указывать на разные участки памяти, если их ссылки указывают на одинаково пустое значение".
Это следует держать в голове, возможно при поиске какого-нибудь бага маппера или конвертера, это может помочь.
Операции с bool?
Неоднозначная ситуация получается со сравнениями Nullable<bool> переменных. Ведь в этом случае, у возможных значений при логических операций, появляется третье состояние, помимо true и false - это null.
Что такое первые два, с точки зрения логики - понятно, истина или ложь.
Но что такое для логики пустота, или ничего - это что-то невозможное, несуществующее, и как в таком случае код будет сравнивать невозможное, например с истиной.

Вывод:

Казалось бы при сложении null и true, мы расчиваем получить в результате null и упасть на вызове .Value. Но при выполнении, null ведет себя как false.
Казалось бы, тоже логично, с какой-то стороны, считать отсутствие значения, как негативное, но совсем нелогично, учитывая, что для всех остальных Nullable Types, при операциях хоть с одним null, мы будем всегда получать null.

Вывод:

Bonus
Для размышлений:
Что будет с запросами в БД, если в C# сравнение bool? дает такие результаты:

Вывод:

А сравнение в SQL такие:

Вывод:

Подсказка:
SQL считает null - чем-то из ряда вон выходящим, и в любом сравнении будет переходить в else, что разнится с логикой в C#. Соответственно с условиями выборки и формировании запроса из C# нужно быть аккуратнее при использовании bool?.
## Источники
Nullable value types - C# reference | Microsoft Learn
Nullable reference types | Microsoft Learn
Notes about C# records and Nullable Reference Types - Event-Driven.io
c# - How is the boxing/unboxing behavior of Nullable possible? - Stack Overflow