Проверка, имеет ли значение переменной DateTime назначенное значение

131

Есть ли в C # простой способ проверить, присвоено ли экземпляру DateTime значение или нет?

мычание
источник

Ответы:

83

Единственный способ иметь переменную, которой не было присвоено значение в C #, - это сделать ее локальной переменной - и в этом случае во время компиляции вы можете сказать, что она не назначена определенно, попытавшись прочитать из нее: )

Я подозреваю, что вы действительно хотите Nullable<DateTime>(или DateTime?с синтаксическим сахаром C #) - сделайте это nullдля начала, а затем назначьте нормальное DateTimeзначение (которое будет преобразовано соответствующим образом). Затем вы можете просто сравнить null(или использовать HasValueсвойство), чтобы увидеть, установлено ли «реальное» значение.

Джон Скит
источник
как насчет проверки, равно ли значение значению даты и времени по умолчанию. Есть ли у такого подхода какие-то незаметные недостатки? if (request.StartDateTime == default (DateTime) {request.StartDateTime = DateTime.Now;}
Менол
8
@Menol: Ну, это не говорит о разнице между полем, которому преднамеренно присвоено значение, default(DateTime)и тем, с которым изначально было именно так. В основном он обрабатывает одно значение в домене как «особое и недоступное для нормального использования», что мне не нравится.
Джон Скит,
298

ты имеешь в виду так:

DateTime datetime = new DateTime();

if (datetime == DateTime.MinValue)
{
    //unassigned
}

или вы можете использовать Nullable

DateTime? datetime = null;

 if (!datetime.HasValue)
 {
     //unassigned
 }
Спасли
источник
5
Только второй из них является пуленепробиваемым. Первый предполагает что-то о ненастроенном представлении DateTime, которое не гарантируется фреймворком. Лично я считаю, что для этого сценария нужно было добавить статический член Unset.
Руперт Роунсли
18
Чтобы добавить то, что сказал @RupertRawnsley, вы должны фактически сравнить со значением по умолчанию (DateTime), которое является значением неназначенного DateTime. Так получилось, что оно равно MinValue, но может измениться.
Цахи Ашер
32

положите это куда-нибудь:

public static class DateTimeUtil //or whatever name
{
    public static bool IsEmpty(this DateTime dateTime)
    {
        return dateTime == default(DateTime);
    }
}

затем:

DateTime datetime = ...;

if (datetime.IsEmpty())
{
    //unassigned
}
sonatique
источник
Мне нравится эта идея, но обратите внимание, что в несколько маловероятном случае, когда переменной DateTime было присвоено значение, которое оказывается значением по умолчанию, этот метод расширения вернет неправильный результат. Единственный способ избежать этого - использовать DateTime, допускающий значение NULL, что уже было предложено. Мне все еще очень нравится (и теперь я использую) ваш ответ, спасибо!
Klicker 02
@Klicker: Спасибо за хороший комментарий, но я не уверен, что понимаю ваше замечание. Насколько я могу судить, == в этом случае всегда будет возвращать true, если datetime эквивалентно значению по умолчанию (DateTime), независимо от того, каким образом datetime в конечном итоге получает значение по умолчанию. Позвольте мне объяснить: на самом деле второй фрагмент в моем ответе неверен, он не будет компилироваться, потому что, если вы считаете, что это тело функции, тогда datetime не назначено, и компилятор откажется его использовать. Поэтому вам нужно будет присвоить ему значение. Это может быть значение по умолчанию (DateTime) прямо или косвенно. Я изменю свой ответ.
сонатика 03
и если в другом контексте datetime является членом класса и оставлено как есть, среда выполнения назначит ему значение по умолчанию (DateTime). Знак == для структур фактически сравнивает содержимое структуры независимо от того, каким образом структура в конечном итоге заполнилась этим содержимым.
сонатика 03
Моя точка зрения действительно относится только к ученикам, и я имею в виду; если у вас есть поле или свойство DateTime уровня класса, которому вы назначили MinValue, ваш IsEmptyметод вернет true, что, вероятно, не то, что вам нужно (потому что оно не пустое - ему было присвоено значение по умолчанию). Думаю, название вашего метода больше подошло бы IsDefaultValue. Поскольку у вас действительно не может быть DateTime, не допускающего значения NULL IsEmpty.
Klicker 03
@Klicker: ах да, хорошо, понял. Вы правы: выбранное мной имя вводит в заблуждение. IsDefaultValueбыло бы лучше
sonatique 05
5

DateTime - это тип значения, поэтому он не может быть нулевым. Если вы думаете DateTime? (Nullable) вы можете использовать:

DateTime? something = GetDateTime();
bool isNull = (something == null);
bool isNull2 = !something.HasValue;
TcKs
источник
5

Я только что узнал, что GetHashCode () для неназначенного datetime всегда равен нулю. Я не уверен, что это хороший способ проверить значение null datetime, потому что я не могу найти никакой документации о том, почему отображается такое поведение.

if(dt.GetHashCode()==0)
{
    Console.WriteLine("DateTime is unassigned"); 
} 
Арктур
источник
1
GetHashCodeвозвращает 0 из - за клещами (внутреннее представление DateTime) также равен 0. Hash код вычисленного следующим образом: unchecked((int)ticks) ^ (int)(ticks >> 32);. Также смотрите здесь: referencesource.microsoft.com/#mscorlib/system/datetime.cs,836
Иван Kochurkin
Большое спасибо. Я пытаюсь сериализовать XML-файл из класса C # и исключить нулевые атрибуты. Это помогло.
Джим Нефф
5

Используйте, Nullable<DateTime>если возможно.

Baretta
источник
3

Я бы сказал, что значение по умолчанию всегда new DateTime(). Итак, мы можем написать

DateTime datetime;

if (datetime == new DateTime())
{
    //unassigned
}
Сабин
источник
2
Это решение уже было предоставлено + Hath в 2008 году и, как добавил + Руперт Ронсли в качестве комментария, не является пуленепробиваемым ...
Роланд Бэр,
0

Я обычно предпочитаю, где это возможно, использовать значение по умолчанию для типов значений, чтобы определить, были ли они установлены. Очевидно, что это невозможно постоянно, особенно с целыми числами, но для DateTimes я думаю, что зарезервировать MinValue для обозначения того, что оно не было изменено, достаточно справедливо. Преимущество этого по сравнению с значениями NULL состоит в том, что на одно место меньше, где вы получите исключение с нулевой ссылкой (и, вероятно, во многих местах, где вам не нужно проверять значение NULL перед доступом к нему!)

Стив Данн
источник
0

Если вы не хотите беспокоиться о проблемах с нулевым значением, например о проверке на null каждый раз, когда вы его используете или обертываете его в какой-то логике, и вы также не хотите беспокоиться о проблемах времени смещения, тогда это как я решил проблему:

startDate = startDate < DateTime.MinValue.AddDays(1) ? keepIt : resetIt

Я просто проверяю, что значение по умолчанию меньше, чем через день после начала времени. Работает как шарм.

Urasquirrel
источник