Як я можу використовувати DateTime.TryParse з Nullable <DateTime>?


115

Я хочу використовувати метод DateTime.TryParse, щоб отримати значення строки datetime рядка в Nullable. Але коли я спробую це:

DateTime? d;
bool success = DateTime.TryParse("some date text", out (DateTime)d);

компілятор мені каже

Аргумент 'out' не класифікується як змінна

Не впевнений, що мені тут потрібно робити. Я також спробував:

out (DateTime)d.Value 

і це не працює. Будь-які ідеї?

Відповіді:


123
DateTime? d=null;
DateTime d2;
bool success = DateTime.TryParse("some date text", out d2);
if (success) d=d2;

(Можуть бути і більш елегантні рішення, але чому б вам просто не зробити щось, як описано вище?)


3
Ви маєте рацію, я шукав більше однолінійного лайнера, щоб виконати це, але я вважаю, що це вдасться. Не любить створювати цю змінну temp, відчуває себе безладно. : - / Схоже, цей сценарій слід краще підтримувати.
Брайан Салліван

1
див. пропозицію Бінарного Вор'єра про те, щоб псуедо-вбудовано це в метод розширення.
Девід Алперт

4
Чому ви кидаєте DateTime в DateTime? Вам не потрібно перевпорядковувати d2, перш ніж передати його в TryParse.
Аарон Пауелл

@Slace - я оновив відповідь, щоб включити вашу пропозицію.
Дрю Ноакс

@Jason Kealey Я сподіваюся, що це вже представлено у VS2012, інакше мені доведеться продовжувати використовувати цей хороший фрагмент коду.
Пімента

161

Як каже Джейсон, ви можете створити змінну потрібного типу та передати її. Ви можете інкапсулювати його власним методом:

public static DateTime? TryParse(string text)
{
    DateTime date;
    if (DateTime.TryParse(text, out date))
    {
        return date;
    }
    else
    {
        return null;
    }
}

... або якщо вам подобається умовний оператор:

public static DateTime? TryParse(string text)
{
    DateTime date;
    return DateTime.TryParse(text, out date) ? date : (DateTime?) null;
}

Або в C # 7:

public static DateTime? TryParse(string text) =>
    DateTime.TryParse(text, out var date) ? date : (DateTime?) null;

5
Я, мабуть, не повинен сперечатися з The Skeet, але ... ви повинні назвати свій метод Parse, оскільки я б очікував, що метод, який називається TryParse, буде дотримуватися конвенції TryParse і повертає булеву форму. ;-)
Містер

@Myster: Ну і в жодному випадку це не дотримується точно існуючої конвенції - ті, хто раніше просто Parseочікував би, що він повернеться DateTimeта кине виняток у випадку невдачі, правда? Але так, ви можете робити все, що завгодно ... і в Noda Time я Parseзамість цього назвав відповідні методи .
Джон Скіт

1
elseКлючове слово НЕ є необхідним (в першому прикладі) , так як крайова частина ifблоку не може бути досягнута.
Джеппе Стіг Нільсен

1
@JeppeStigNielsen: Так, це зайве - але це може бути стилістично кращим для симетрії. Це просто особисті уподобання (і я не послідовний, теж ...)
Джон Скіт

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

20

Ось трохи стислий випуск того, що запропонував Джейсон:

DateTime? d; DateTime dt;
d = DateTime.TryParse(DateTime.Now.ToString(), out dt)? dt : (DateTime?)null;

18

Ви не можете, тому що Nullable<DateTime>це інший тип DateTime. Для цього потрібно написати власну функцію,

public bool TryParse(string text, out Nullable<DateTime> nDate)
{
    DateTime date;
    bool isParsed = DateTime.TryParse(text, out date);
    if (isParsed)
        nDate = new Nullable<DateTime>(date);
    else
        nDate = new Nullable<DateTime>();
    return isParsed;
}

Сподіваюся, це допомагає :)

Редагувати: Видалено (очевидно) неправильно перевірений метод розширення, оскільки (як вказує деяка погана заподіяність) методи розширення, які намагаються змінити параметр "цей", не працюватимуть із Value Types.

PS Поганий Хор - старий друг :)


Я не хочу вводити дату [як ви використовуєте це як параметр] Добре, я перестану бути вибагливим!
Рубен Бартелінк

У мене немає компілятора, але так як DateTime є типом значення, чи компілюється метод розширення?
Рубен Бартелинк

Результат не повертається, якщо ви його не зробите - публічний клас [TestFixture] WhenExtending {[Test] public void TryParseShouldWork () {DateTime? x = null; var res = Externders.TryParse (x, "1/1/1990"); Assert.IsTrue (res)
Рубен Бартелінк

; Assert.That (x! = Null); }} виходить з ладу на Assert.That, тобто результат не змінюється, оскільки DateTime - це тип значення (що завжди є гарним питанням про видалення бур'янів на екранах телефону: D)
Ruben Bartelink

(OBV перший (не розширення) буде працювати, але він повинен бути зовнішнім, а не поновитим - і вам слід скасувати результат, якщо він не зможе вписатись в API API TryXXX взагалі - Досить впевнений, що FDG згадує про це. Людина, я Я прискіпливий!
Рубен Бартелінк

4

Що щодо створення методу розширення?

public static class NullableExtensions
{
    public static bool TryParse(this DateTime? dateTime, string dateString, out DateTime? result)
    {
        DateTime tempDate;
        if(! DateTime.TryParse(dateString,out tempDate))
        {
            result = null;
            return false;
        }

        result = tempDate;
        return true;

    }
}

2
Для чого це перший параметр dateTime? Він ніколи не використовується.
Майк Зборай

1
@mikez - ось як працюють методи розширення, його використовує компілятор, щоб знати, що це повинен бути метод розширення.
Ерік Функенбуш

3
@MystereMan Я знаю, що таке метод розширення. Більш доцільним буде підпис методу розширення DateTime? TryParse(this string dateString). Ця реалізація просто химерна.
Майк Зборай

3
@mikez - тоді чому ти запитав, для чого це? Навіщо забруднювати простір імен рядків, коли він потрібен лише для дати? Мета - надати аналог DateTime.TryParse, що є DateTime? .TryParse
Ерік Funkenbusch

1
@ErikFunkenbusch Цей метод розширення не дозволить синтаксису виклику як (DateTime?).TryParse( ... )або Nullable<DateTime>.TryParse( ... ). Отже, Майк z правильний, це дурний підпис методу.
Джеппе Стіг Нільсен

1

Я не бачу, чому Microsoft не впоралася з цим. Розумний маленький корисний метод для вирішення цього питання (у мене була проблема з int, але заміна int з DateTime буде таким же ефектом, могла б бути .....

    public static bool NullableValueTryParse(string text, out int? nInt)
    {
        int value;
        if (int.TryParse(text, out value))
        {
            nInt = value;
            return true;
        }
        else
        {
            nInt = null;
            return false;
        }
    }

1

Це один лайнер, який ви шукаєте для:

DateTime? d = DateTime.TryParse("some date text", out DateTime dt) ? dt : null;

Якщо ви хочете зробити це правильним методом TryParse псевдо-розширення, ви можете зробити це:

public static bool TryParse(string text, out DateTime? dt)
{
    if (DateTime.TryParse(text, out DateTime date))
    {
        dt = date;
        return true;
    }
    else
    {
        dt = null;
        return false;
    }
}

@robnick Чим це відрізняється від того, що я сказав?
cpcolella

1
Ігноруйте мій попередній коментар (я підтримав ваше рішення!), Для останнього C # мені потрібно було передати нуль: DateTime? d = DateTime.TryParse (бла, поза DateTime dt)? dt: (DateTime?) null;
robnick


-3

Крім того, якщо ви не переймаєтесь можливим винятком винятків, ви можете змінити TryParse для Parse:

DateTime? d = DateTime.Parse("some valid text");

Хоча булевий показник не вказує і на успіх, він може бути практичним у деяких ситуаціях, коли ви знаєте, що вхідний текст завжди буде дійсним.

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