Перевірка, чи не було вказано значення змінної DateTime


131

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

Відповіді:


83

Єдиний спосіб мати змінну, якій не було призначено значення в C #, це те, що вона є локальною змінною - у цьому випадку під час компіляції ви можете сказати, що вона точно не призначається, намагаючись прочитати з неї: )

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


як щодо перевірки того, чи є значення рівним значенню часу за замовчуванням. Чи є якийсь непомітний недолік цього підходу? if (request.StartDateTime == за замовчуванням (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
}

Мені подобається ця ідея, але зауважте, що у дещо неправдоподібному випадку, коли змінній DateTime було призначено значення, яке трапляється за замовчуванням, цей метод розширення поверне неправильний результат. Єдиний спосіб уникнути цього - використовувати зведений DateTime, який вже було запропоновано. Я все ще дуже люблю (і зараз я використовую) вашу відповідь, хоча, дякую!
Кликер

@Klicker: Дякую за ваш приємний коментар, але я не впевнений, що розумію ваше зауваження. Наскільки я можу сказати == у цьому випадку завжди повернеться true, коли datetime еквівалентно типовому (DateTime), незалежно від того, яким способом для timetime буде призначено значення за замовчуванням. Дозвольте мені пояснити: насправді другий фрагмент у моїй відповіді невірний, він не буде компілюватися, оскільки, якщо ви вважаєте, що це тіло функції, то timetime не призначений, і компілятор відмовиться його використовувати. Тож вам доведеться призначити йому значення. Це може бути за замовчуванням (DateTime) прямо або опосередковано. Я зміню свою відповідь.
sonatique

і якщо в іншому контексті datetime є членом класу, і він залишається таким, як є, час виконання йому призначить за замовчуванням (DateTime). Структури == для структур насправді порівнюють вміст структури, незалежно від того, яким чином завершення структури наповнюється цим вмістом.
sonatique

Моя думка стосується лише членів класу, і те, що я маю на увазі, це; якщо у вас є поле DateTime або рівень властивості класу, якому ви призначили MinValue, ваш IsEmptyметод поверне true, що, мабуть, не те, що ви хотіли б (оскільки він не порожній - йому було призначено значення за замовчуванням). Я думаю, що назва вашого методу більше відповідатиме IsDefaultValue. Оскільки ви не можете насправді мати ненульовий DateTime це IsEmpty.
Кликер

@Klicker: ах так, добре, зрозуміло. Ви маєте рацію: ім’я, яке я вибрав, вводить в оману. IsDefaultValueбуло б краще
sonatique

5

DateTime - тип значення, тому він ніколи не може бути нульовим. Якщо ви думаєте DateTime? (Зніміть) ви можете використовувати:

DateTime? something = GetDateTime();
bool isNull = (something == null);
bool isNull2 = !something.HasValue;

5

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

if(dt.GetHashCode()==0)
{
    Console.WriteLine("DateTime is unassigned"); 
} 

1
GetHashCodeповертає 0 з - за кліщами (внутрішнє уявлення DateTime) також дорівнює 0. Hash код обчисленого таким чином: unchecked((int)ticks) ^ (int)(ticks >> 32);. Також дивіться тут: referenceource.microsoft.com/#mscorlib/system/datetime.cs,836
Іван Кочуркін

Велике спасибі. Я намагаюся серіалізувати XML-файл із класу C # та виключити нульові атрибути. Це допомогло.
Джим Нефф


3

Я б сказав, що значення за замовчуванням завжди new DateTime(). Так ми можемо писати

DateTime datetime;

if (datetime == new DateTime())
{
    //unassigned
}

2
Це рішення вже було надано + Hath у 2008 році і, як додав + Руперт Роунслі, як коментар, не є кулезахисним ...
Roland Bär

0

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


0

Якщо ви не хочете турбуватися про проблеми з нульовим значенням, такі як перевірка на нуль кожного разу, коли ви його використовуєте, або загортання в якусь логіку, і вам також не хочеться турбуватися про проблеми з компенсацією часу, тоді це як я вирішив проблему:

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

Я просто перевіряю, що значення за замовчуванням менше ніж через добу після початку часу. Працює як шарм.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.