Pergunta
Eu tenho procurado muito, mas não conseguiu encontrar uma solução. Como você lida com um DateTime que deve ser capaz de conter um valor não inicializado (equivalente a null)? Eu tenho uma classe que pode ter um conjunto valor da propriedade DateTime ou não. Eu estava pensando em inicializar o titular da propriedade para DateTime.MinValue, que então poderia ser facilmente verificada. Eu acho que esta é uma pergunta muito comum, como você faz isso?
Solução
Para DateTimes normais, se você não inicializá-los em tudo, então eles vão corresponder DateTime.MinValue
, porque é um tipo de valor, em vez de um tipo de referência.
Você também pode usar um DateTime anulável, como este:
DateTime? MyNullableDate;
Ou a forma mais:
Nullable<DateTime> MyNullableDate;
E, finalmente, há um construído em forma de referenciar o padrão de qualquer tipo. Isso retorna null
para tipos de referência, mas para o nosso exemplo DateTime ele irá retornar o mesmo que DateTime.MinValue
:
default(DateTime)
Outras dicas
Se você estiver usando o .NET 2.0 (ou posterior), você pode usar o tipo anulável:
DateTime? dt = null;
ou
Nullable<DateTime> dt = null;
, em seguida, mais tarde:
dt = new DateTime();
E você pode verificar o valor com:
if (dt.HasValue)
{
// Do something with dt.Value
}
Ou você pode usá-lo como:
DateTime dt2 = dt ?? DateTime.MinValue;
Você pode ler mais aqui:
http://msdn.microsoft.com/en-us/library/b3h38hb0.aspx
DateTime? MyDateTime {get; set;}
MyDateTime = (dr["f1"] == DBNull.Value) ? (DateTime?)null : ((DateTime)dr["f1"]);
A seguir caminho funciona bem
myClass.PublishDate = toPublish ? DateTime.Now : (DateTime?)null;
Por favor, note que a propriedade PublishDate deve ser DateTime?
eu consideraria usando um anuláveis ??tipos .
DateTime? myDate
vez de DateTime myDate
.
Você pode usar uma classe anulável.
DateTime? date = new DateTime?();
Você pode usar um DateTime anulável para isso.
Nullable<DateTime> myDateTime;
ou a mesma coisa escrito assim:
DateTime? myDateTime;
Eu sempre definir o tempo para DateTime.MinValue
. Desta forma, eu não obter qualquer NullErrorException e posso compará-lo para uma data que eu sei que não está definido.
É importante ressaltar que, enquanto uma variável DateTime
não pode ser null
, ele ainda pode ser comparado a null
sem um erro do compilador:
DateTime date;
...
if(date == null) // <-- will never be 'true'
...
Você pode definir o DateTime para Nullable. Por padrão DateTime não é anulável. Você pode torná-lo nulo em um par de formas. Usando um ponto de interrogação após o tipo DateTime? MyTime ou usando o estilo genérico Nullable. Eu adicionei um par de links no MSDN.
Apenas ser avisado - Ao usar um Nullable sua, obviamente, não é mais um 'puro' datetime objeto, como tal, você não pode acessar os membros DateTime diretamente. Vou tentar explicar.
Ao usar Nullable <> você está envolvendo basicamente DateTime em um recipiente (obrigado genéricos) das quais é anulável - obviamente o seu propósito. Este recipiente tem suas próprias propriedades que você pode chamar que irá proporcionar o acesso ao objeto DateTime acima mencionado; depois de usar a propriedade correta - neste caso Nullable.Value - então você tem acesso aos membros DateTime padrão, propriedades etc
.Então - agora a questão vem à mente como a melhor maneira de acessar o objeto DateTime. Existem algumas maneiras, o número 1 é de longe o melhor e 2 é "cara porquê".
-
Usando a propriedade Nullable.Value,
DateTime date = myNullableObject.Value.ToUniversalTime(); //Works
DateTime date = myNullableObject.ToUniversalTime(); //Not a datetime object, fails
-
Convertendo o objecto nulo em datetime usando Convert.ToDateTime (),
DateTime date = Convert.ToDateTime(myNullableObject).ToUniversalTime(); //works but why...
Embora a resposta é bem documentada neste momento, acredito que o uso de Nullable foi provavelmente vale postagem sobre. Desculpe se você discordar.
edit:. Removido uma terceira opção, uma vez que foi um pouco demasiado específica e caso dependente
Embora todos já lhe deu a resposta, eu vou falar uma forma que torna mais fácil para passar uma data e hora em uma função
[ERROR: Não é possível converter System.DateTime? para System.DateTime]
DateTime? dt = null;
DateTime dte = Convert.ToDateTime(dt);
Agora você pode passar DTE dentro da função sem quaisquer problemas.
Se você é, às vezes, esperando nula você poderia usar algo como isto:
var orderResults = Repository.GetOrders(id, (DateTime?)model.DateFrom, (DateTime?)model.DateTo)
Em seu uso de data e hora nulo capaz repositório.
public Orders[] GetOrders(string id, DateTime? dateFrom, DateTime? dateTo){...}
Eu tive o mesmo problema que eu tive que dar nulo como parâmetro para DateTime durante a execução de teste de unidade para Lança ArgumentNullException.It trabalhou no meu caso usando a seguinte opção:
Assert.Throws<ArgumentNullException>(()=>sut.StartingDate = DateTime.Parse(null));
Dada a natureza de uma data / hora tipo de dados não pode conter um valor null
, ou seja, ele precisa conter um valor, ele não pode estar em branco ou conter nada. Se você marcar uma variável de data / hora como nullable
então só você pode atribuir um valor nulo a ele. Então, o que você está procurando fazer é uma de duas coisas (pode haver mais, mas eu só posso pensar em dois):
-
Atribuir um valor de data mínimo / hora para a variável, se você não tem um valor para ele. Você pode atribuir um valor máximo de data / hora, bem como - Independentemente da forma como lhe convier. Apenas certifique-se que você é consistente local de largura ao verificar seus valores data / hora. Decidir sobre o uso
min
oumax
e ficar com ela. -
Mark sua data variável / hora como
nullable
. Desta forma, você pode definir a variável de data / hora paranull
se você não tem uma variável a ele.
Deixe-me demonstrar o meu primeiro ponto usando um exemplo. O tipo de variável DateTime
não pode ser definido como nulo, ele precisa de um valor, neste caso eu vou configurá-lo para o valor mínimo da DateTime
se não houver nenhum valor.
O meu cenário é que eu tenho uma classe BlogPost
. Ele tem muitos campos / propriedades diferentes, mas eu escolhi usar apenas dois para este exemplo. DatePublished
é quando o artigo foi publicado no site e tem que conter um valor de data / hora. DateModified
é quando um post for modificado, por isso não tem de conter um valor, mas pode conter um valor.
public class BlogPost : Entity
{
public DateTime DateModified { get; set; }
public DateTime DatePublished { get; set; }
}
Usando ADO.NET
para obter os dados do banco de dados (DateTime.MinValue
atribuir é não há nenhum valor):
BlogPost blogPost = new BlogPost();
blogPost.DateModified = sqlDataReader.IsDBNull(0) ? DateTime.MinValue : sqlDataReader.GetFieldValue<DateTime>(0);
blogPost.DatePublished = sqlDataReader.GetFieldValue<DateTime>(1);
Você pode fazer o meu segundo ponto, marcando o campo DateModified
como nullable
. Agora você pode configurá-lo para null
se não houver nenhum valor para ele:
public DateTime? DateModified { get; set; }
Usando ADO.NET
para obter os dados do banco de dados, ele vai olhar um pouco diferente para a forma como foi feito acima (atribuindo null
vez de DateTime.MinValue
):
BlogPost blogPost = new BlogPost();
blogPost.DateModified = sqlDataReader.IsDBNull(0) ? (DateTime?)null : sqlDataReader.GetFieldValue<DateTime>(0);
blogPost.DatePublished = sqlDataReader.GetFieldValue<DateTime>(1);
Espero que isso ajude a esclarecer qualquer confusão. Dado que a minha resposta é de cerca de 8 anos mais tarde você é provavelmente um programador C # especialista até agora:)