Como faço para usar DateTime.ExperimenteParse com um Nullable <DateTime>?


115

Eu quero usar o método DateTime.ExperimenteParse para obter o valor de data e hora de uma string em um Nullable. Mas quando eu tento isso:

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

o compilador me diz

argumento 'out' não é classificado como uma variável

Não tenho certeza do que preciso fazer aqui. Eu também tentei:

out (DateTime)d.Value 

e isso também não funciona. Alguma ideia?

Respostas:


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

(Pode haver soluções mais elegantes, mas por que você simplesmente não faz algo como acima?)


3
Você está certo, eu estava procurando mais de uma linha para fazer isso, mas suponho que isso vai servir. Não gosto de criar essa variável temporária, parece confuso. : - / Parece que este cenário deve ser melhor suportado.
— Brian Sullivan,

1
veja a sugestão de Binary Worrier para psuedo-inline isso em um método de extensão.
— David Alpert,

4
Por que você está transmitindo um DateTime para um DateTime? Você não precisa refazer o d2 antes de passá-lo para o TryParse.
— Aaron Powell

@Slace - Eu atualizei a resposta para incorporar sua sugestão.
— Drew Noakes

@Jason Kealey Espero que isso já tenha sido introduzido no VS2012, caso contrário, terei que continuar usando este bom código.
— Pimenta

161

Como diz Jason, você pode criar uma variável do tipo certo e passar isso. Você pode querer encapsulá-lo em seu próprio método:

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

... ou se você gosta do operador condicional:

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

Ou em C # 7:

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

5
Eu provavelmente não deveria discutir com o Skeet, mas ... você deve chamar seu método Parse, já que eu esperaria que um método chamado TryParse seguisse a convenção TryParse e retornasse um booleano. ;-)
— Myster

@Myster: Bem, em nenhum dos casos ele segue exatamente a convenção existente - aqueles que costumavam apenas Parseesperariam que ele retornasse DateTimee gerasse uma exceção em caso de falha, certo? Mas sim, você pode fazer o que quiser ... e no Tempo de Noda, nomeei os métodos relevantes Parse.
— Jon Skeet

1
A elsepalavra-chave é desnecessária (em seu primeiro exemplo), pois o ponto final do ifbloco nunca pode ser alcançado.
— Jeppe Stig Nielsen

1
@JeppeStigNielsen: Sim, é desnecessário - mas pode ser estilisticamente preferível para simetria. É apenas uma preferência pessoal (e também não sou consistente ...)
— Jon Skeet

3
@Kiquenet: o uso de else deixa mais claro que um ou outro caminho será percorrido e ambos retornarão. Sou contra código aninhado massivamente, mas neste caso não é realmente um problema IMO.
— Jon Skeet de

20

Aqui está uma edição ligeiramente concisa do que Jason sugeriu:

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

18

Você não pode porque Nullable<DateTime>é um tipo diferente de DateTime. Você precisa escrever sua própria função para fazer isso,

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;
}

Espero que isto ajude :)

EDITAR: Removido o método de extensão (obviamente) testado de maneira inadequada, porque (como apontado por alguns hoor ruins) os métodos de extensão que tentam alterar o parâmetro "this" não funcionarão com Tipos de valor.

PS O Bad Hoor em questão é um velho amigo :)


Você não quer iniciar a data [já que você está usando como um parâmetro de saída] OK, vou parar de ser exigente!
— Ruben Bartelink

Não tenho um compilador comigo, mas como DateTime é um tipo de valor, o método de extensão def compila?
— Ruben Bartelink

O resultado não volta a menos que você o faça - [TestFixture] public class WhenExtending {[Test] public void TryParseShouldWork () {DateTime? x = nulo; var res = Externders.ExperimenteParse (x, "01/01/1990"); Assert.IsTrue (res)
— Ruben Bartelink

; Assert.That (x! = Null); }} falha na Assert. Isso, ou seja, o resultado não é modificado porque DateTime é um tipo de valor (o que é sempre uma boa questão de eliminação nas telas de telefone: D)
— Ruben Bartelink

(óbvio que o primeiro (sem extensão) funcionará, mas deve estar fora, não ref - e você deve anular o resultado se ele não se ajustar às APIs TryXXX em geral - Tenho certeza que o FDG menciona isso. Cara, estou Eu exigente!
— Ruben Bartelink

4

Que tal criar um método de extensão?

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
Qual é o primeiro parâmetro,, dateTimepara? Nunca é usado.
— Mike Zboray

1
@mikez - é assim que os métodos de extensão funcionam, é usado pelo compilador para saber que deve ser um método de extensão.
— Erik Funkenbusch

3
@MystereMan Eu sei o que é um método de extensão. Uma assinatura mais apropriada para um método de extensão seria DateTime? TryParse(this string dateString). Essa implementação é simplesmente bizarra.
— Mike Zboray

3
@mikez - então por que você perguntou para que era? Por que poluir o namespace da string quando você só precisa dele para datetime? O objetivo é fornecer um análogo a DateTime.ExperimenteParse que é DateTime?. TryParse
— Erik Funkenbusch

1
@ErikFunkenbusch Este método de extensão não permitirá uma sintaxe de chamada como (DateTime?).TryParse( ... )ou Nullable<DateTime>.TryParse( ... ). Então mike z está certo, essa é uma assinatura boba para o método.
— Jeppe Stig Nielsen

1

Não vejo por que a Microsoft não lidou com isso. Um pequeno método utilitário inteligente para lidar com isso (tive o problema com int, mas substituir int por DateTime terá o mesmo efeito, pode ser ...

    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

Este é o revestimento que você está procurando:

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

Se quiser torná-lo um método de pseudo-extensão TryParse adequado, você pode fazer isso:

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 Como isso é diferente do que eu disse?
— cpcolella

1
Ignore meu comentário anterior (eu votei sua solução!), Para o C # mais recente, precisei lançar o null: DateTime? d = DateTime.ExperimenteParse (blah, out DateTime dt)? dt: (DateTime?) null;
— robnick

1

Aqui está uma solução de linha única:

DateTime? d = DateTime.TryParse("text", out DateTime parseDate) ? parseDate : (DateTime?)null;

-3

Como alternativa, se você não estiver preocupado com a possível exceção gerada, pode alterar o TryParse para o Parse:

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

Embora também não haja um booleano indicando o sucesso, pode ser prático em algumas situações em que você sabe que o texto de entrada sempre será válido.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.