#c# #datetime #nullable
Вопрос:
Я хочу использовать дату и время.Метод TryParse для преобразования значения даты и времени строки в значение, допускающее значение Null. Но когда я попробую это:
DateTime? d;
bool success = DateTime.TryParse("some date text", out (DateTime)d);
компилятор говорит мне
аргумент «out» не классифицируется как переменная
Не уверен, что мне нужно здесь делать. Я тоже пытался:
out (DateTime)d.Value
и это тоже не работает. Есть какие-нибудь идеи?
Ответ №1:
Как говорит Джейсон, вы можете создать переменную нужного типа и передать ее. Возможно, вы захотите инкапсулировать его в свой собственный метод:
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;
Комментарии:
1. Наверное, мне не следовало бы спорить со Скитом, но… вы должны вызвать свой метод Parse, так как я ожидал бы, что метод под названием TryParse будет следовать соглашению TryParse и возвращать логическое значение. 😉
2. @Myster: Ну, ни в том, ни в другом случае это не соответствует точному существующему соглашению — те, кто привык, просто
Parse
ожидали бы, что оно вернетсяDateTime
и выдаст исключение при сбое, верно? Но да, ты можешь делать все, что захочешь… и во время Noda я вместо этого назвал соответствующие методыParse
.3.
else
Ключевое слово не является необходимым (в вашем первом примере), так как конечная точкаif
блока никогда не может быть достигнута.4. @JeppeStigNielsen: Да, в этом нет необходимости, но это может быть стилистически предпочтительнее для симметрии. Это просто личное предпочтение (и я тоже не последователен…)
5. @Kiquenet: использование else проясняет, что будет выбран тот или иной путь, и оба вернутся. Я против массивно вложенного кода, но в данном случае это действительно не проблема, ИМО.
Ответ №2:
DateTime? d=null;
DateTime d2;
bool success = DateTime.TryParse("some date text", out d2);
if (success) d=d2;
(Могут быть и более элегантные решения, но почему бы вам просто не сделать что-то, как описано выше?)
Комментарии:
1. Вы правы, я искал более простой способ сделать это, но я полагаю, что этого будет достаточно. Не нравится создавать эту временную переменную, чувствуется беспорядок. :-/ Похоже, этот сценарий следует лучше поддерживать.
2. смотрите предложение Binary Worrier для psuedo-встроить это в метод расширения.
3. Почему вы переводите дату — время в дату-время? Вам не нужно переделывать d2 перед передачей его в пробный анализ.
4. @Slace-я обновил ответ, чтобы включить ваше предложение.
5. @Jason Kealey Я надеюсь, что это уже будет представлено в VS2012, иначе мне придется продолжать использовать этот хороший фрагмент кода.
Ответ №3:
Вот слегка сокращенное изложение того, что предложил Джейсон:
DateTime? d; DateTime dt;
d = DateTime.TryParse(DateTime.Now.ToString(), out dt)? dt : (DateTime?)null;
Ответ №4:
Вы не можете, потому 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;
}
Надеюсь, это поможет 🙂
ИЗМЕНИТЬ: Удален (очевидно) неправильно протестированный метод расширения, потому что (как указано некоторыми плохими учителями) методы расширения, которые пытаются изменить параметр «this», не будут работать с типами значений.
P.S. Плохая Шлюха, о которой идет речь, — мой старый друг 🙂
Комментарии:
1. Ты не хочешь вводить дату [так как ты используешь ее как выходной параметр] Хорошо, я перестану быть придирчивым!
2. У меня нет компилятора, но, поскольку DateTime является типом значения, компилируется ли метод расширения def?
3. Результат не возвращается, если вы не сделаете это — [TestFixture] публичный класс при расширении { [Тест] публичная пустота TryParseShouldWork() { Дата и время? x = ноль; var res = Внешние. Попробуйте проанализировать( x, «1/1/1990» ); Утверждайте. ИСТРУ( res )
4. ;Утверждать. Это( x != null ); } } сбой при утверждении. Это, т. е. результат не изменяется, поскольку DateTime является типом значения (что всегда является хорошим вопросом для исключения на экранах телефонов :D)
5. (obv первый (без расширения) будет работать, но он должен быть отключен, а не ref-и вы должны аннулировать результат, если он не соответствует API TryXXX в целом — Почти уверен, что FDG упоминает об этом. Блин, какой же я придирчивый!
Ответ №5:
Как насчет создания метода расширения?
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;
}
}
Комментарии:
1. Для чего нужен этот первый параметр,
dateTime
,? Он никогда не используется.2. @mikez — вот как работают методы расширения, компилятор использует их, чтобы знать, что это должен быть метод расширения.
3. @MystereMan Я знаю, что такое метод расширения. Более подходящей подписью для метода расширения была бы
DateTime? TryParse(this string dateString)
. Эта реализация просто странная.4. @mikez — тогда почему ты спросил, для чего это было? Зачем загрязнять пространство имен строк, если оно нужно только для даты и времени? Цель состоит в том, чтобы обеспечить аналог даты и времени. Попробуйте проанализировать, что такое дата-время?. Попробуйте проанализировать
5. @ErikFunkenbusch Этот метод расширения не допускает синтаксис вызова, подобный
(DateTime?).TryParse( ... )
илиNullable<DateTime>.TryParse( ... )
. Так что Майк зи прав, это глупая подпись для метода.
Ответ №6:
Я не понимаю, почему 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;
}
}
Ответ №7:
Вот однострочное решение:
DateTime? d = DateTime.TryParse("text", out DateTime parseDate) ? parseDate : (DateTime?)null;
Комментарии:
1. итак…вы только что скопировали мой ответ 4 месяца спустя?
Ответ №8:
Это тот лайнер, который вы ищете:
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;
}
}
Комментарии:
1. @robnick, чем это отличается от того, что я сказал?
2. Проигнорируйте мой предыдущий комментарий (я поддержал ваше решение!), для последней версии C# мне нужно было ввести значение null: дата-время? d = Дата и время. Попробуйте проанализировать(бла, дата и время dt) ? dt : (Дата и время?)значение null;
Ответ №9:
В качестве альтернативы, если вас не беспокоит возможное возникшее исключение, вы можете изменить пробный анализ для разбора:
DateTime? d = DateTime.Parse("some valid text");
Хотя логического значения, указывающего на успех, также не будет, это может быть практично в некоторых ситуациях, когда вы знаете, что введенный текст всегда будет действительным.