Лучше DateTime? или использовать значение по умолчанию (DateTime) для NULL?

Я разрабатываю веб-сайт С#/NHibernate, в котором есть частная система обмена сообщениями. Я бы хотел, чтобы администраторы проверяли, когда и когда сообщение было прочитано пользователем, и вместе выделите те сообщения, которые еще не были прочитаны пользователями. Для достижения обоих я нашел два варианта:

Вариант 1

class Message
{
    DateTime? Read;
}

где Read==null означает, что еще не прочитано

Вариант 2

class Message
{
    DateTime Read;
}

где Read==default(DateTime) (1 января 1 A.D., 0:00:00) означает, что еще не прочитано.

В университете меня научили использовать значение NULL для обработки всех особых случаев, а также использование типа с нулевым значением кажется хорошим выбором, так как проще читать непрочитанные сообщения, проверяя, являются ли они NULL или нет.

Но, используя типы с нулевым значением, по крайней мере, включает в себя бокс и распаковку в коде, при этом производительность снижается. С другой стороны, запрос на непрочитанные сообщения означает сравнение значения (но его можно индексировать)

Мой вопрос

Каков ваш предложенный подход для этого? Что предложили бы лучшие практики в этом случае?

Ответы

Ответ 1

Используйте DateTime?. Его особая цель - избегать использования зарезервированных значений (иначе называемых "магическими числами" ) для представления особых случаев, таких как null.

Кроме того, использование типа с нулевым значением не вводит сам бокс. Любые значения, которые были бы помещены в коробку, будут, но вы не будете вводить какой-либо бокс просто путем переключения. Тип Nullable<T> на самом деле является структурой, а возможность сравнения с null (или Nothing в VB.NET) является строго условным языком. Под обложками он преобразуется в проверку свойства HasValue.

Ответ 2

Использование типов с нулевым значением существенно не снижает производительность по сравнению с альтернативными подходами. Оба DateTime и DateTime? являются структурами, и здесь нет бокса. Использование нулевого значения - правильный выбор.

Ответ 3

Задайте себе один и тот же вопрос при работе с числовыми значениями. Использую ли я 0? Что делать, если 0 имеет реальный смысл? NULL - это отсутствие ценности. 99 раз из 100, пойти с тем, что делает цель кода наиболее очевидной. Что касается производительности, даже если она есть, она будет бледна по сравнению с любыми проблемами производительности, присущими вашему собственному коду.

Ответ 4

Как сказал Марк и Адам, нулевой тип - это путь. Вы не увидите хита производительности, и это сделает запрос намного проще.

Ответ 5

Чтобы понять, что сказал Марк, если у вас возникла проблема с использованием нулевого типа в клиентском коде, вы можете установить его на DateTime.MinValue, а затем на уровне buisiness, переключиться на значение NULL. Затем вы можете подавать нулевой тип в DataAccess. Это помогает сохранить слой абстракции для использования нулевых значений.

Ответ 6

Мне не хватает трюка?

class Message
{
    DateTime LastRead;
    bool Read;
}