Domanda

Ho cercato molto ma non sono riuscito a trovare una soluzione. Come gestisci un DateTime che dovrebbe essere in grado di contenere un valore non inizializzato (equivalente a null)? Ho una classe che potrebbe avere un valore di proprietà DateTime impostato o meno. Stavo pensando di inizializzare il titolare della proprietà su DateTime.MinValue, che poi poteva essere facilmente controllato. Immagino che questa sia una domanda abbastanza comune, come si fa?

È stato utile?

Soluzione

Per i DateTime normali, se non li inizializzi affatto, corrisponderanno a DateTime.MinValue , perché è un tipo di valore anziché un tipo di riferimento.

Puoi anche usare un DateTime nullable, come questo:

DateTime? MyNullableDate;

O la forma più lunga:

Nullable<DateTime> MyNullableDate;

E, infine, esiste un modo integrato per fare riferimento al valore predefinito di qualsiasi tipo. Questo restituisce null per i tipi di riferimento, ma per il nostro esempio DateTime restituirà lo stesso DateTime.MinValue :

default(DateTime)

Altri suggerimenti

Se stai usando .NET 2.0 (o successivo) puoi usare il tipo nullable:

DateTime? dt = null;

o

Nullable<DateTime> dt = null;

poi più tardi:

dt = new DateTime();

E puoi controllare il valore con:

if (dt.HasValue)
{
  // Do something with dt.Value
}

O puoi usarlo come:

DateTime dt2 = dt ?? DateTime.MinValue;

Puoi leggere di più qui:
http://msdn.microsoft.com/en-us/library/b3h38hb0.aspx

DateTime? MyDateTime {get; set;}

MyDateTime = (dr["f1"] == DBNull.Value) ? (DateTime?)null : ((DateTime)dr["f1"]);

Anche il modo seguente funziona

myClass.PublishDate = toPublish ? DateTime.Now : (DateTime?)null;

La proprietà PublishDate dovrebbe essere DateTime?

Prenderei in considerazione l'utilizzo di un tipi nullable .

DateTime? myDate anziché DateTime myDate .

Puoi usare una classe nullable.

DateTime? date = new DateTime?();

Puoi usare un DateTime nullable per questo.

Nullable<DateTime> myDateTime;

o la stessa cosa scritta in questo modo:

DateTime? myDateTime;

Ho sempre impostato l'ora su DateTime.MinValue . In questo modo non ottengo alcuna NullErrorException e posso confrontarlo con una data che so non è impostata.

Vale la pena sottolineare che, sebbene una variabile DateTime non possa essere null , può comunque essere confrontata con null senza un errore del compilatore :

DateTime date;
...
if(date == null) // <-- will never be 'true'
  ...

È possibile impostare DateTime su Nullable. Per impostazione predefinita, DateTime non è nullable. Puoi renderlo nullable in un paio di modi. Utilizzando un punto interrogativo dopo il tipo DateTime? myTime o usando lo stile generico Nullable. Ho aggiunto un paio di collegamenti su msdn.

Uso di Nullable

Nullable

Basta essere avvisati: quando si utilizza una Nullable, ovviamente non è più un oggetto datetime "puro", pertanto non è possibile accedere direttamente ai membri DateTime. Proverò a spiegare.

Utilizzando Nullable < > stai fondamentalmente avvolgendo DateTime in un contenitore (grazie generici) di cui è nullable - ovviamente il suo scopo. Questo contenitore ha le sue proprietà che è possibile chiamare che forniranno l'accesso al suddetto oggetto DateTime; dopo aver usato la proprietà corretta - in questo caso Nullable.Value - avrai quindi accesso ai membri DateTime standard, alle proprietà ecc.

Quindi - ora mi viene in mente il problema sul modo migliore per accedere all'oggetto DateTime. Ci sono alcuni modi, il numero 1 è di gran lunga il migliore e 2 è "amico perché".

  1. Uso della proprietà Nullable.Value,

    DateTime date = myNullableObject.Value.ToUniversalTime (); // Opere

    DateTime date = myNullableObject.ToUniversalTime (); // Non è un oggetto datetime, non riesce

  2. Conversione dell'oggetto nullable in datetime utilizzando Convert.ToDateTime (),

    DateTime date = Convert.ToDateTime (myNullableObject) .ToUniversalTime (); // funziona ma perché ...

Anche se la risposta è ben documentata a questo punto, credo che valga la pena postare l'uso di Nullable. Scusa se non sei d'accordo.

modifica: rimossa una terza opzione perché era un po 'troppo specifica e dipendente dal caso.

Sebbene tutti ti abbiano già dato la risposta, menzionerò un modo che semplifica il passaggio di un datetime in una funzione

[ERRORE: impossibile convertire system.datetime? a system.datetime]

DateTime? dt = null;
DateTime dte = Convert.ToDateTime(dt);

Ora puoi passare dte all'interno della funzione senza problemi.

Se, a volte, ti aspetti un valore nullo, potresti usare qualcosa del genere:

var orderResults = Repository.GetOrders(id, (DateTime?)model.DateFrom, (DateTime?)model.DateTo)

Nel tuo repository usa datetime abilitato a null.

public Orders[] GetOrders(string id, DateTime? dateFrom, DateTime? dateTo){...}

Ho avuto lo stesso problema che avevo di dare Null come parametro per DateTime durante l'esecuzione del test unitario per Throws ArgumentNullException. Nel mio caso ha funzionato usando la seguente opzione:

Assert.Throws<ArgumentNullException>(()=>sut.StartingDate = DateTime.Parse(null));

Data la natura di un tipo di dati data / ora, non può contenere un valore null , ovvero deve contenere un valore, non può essere vuoto o contenere nulla. Se contrassegni una variabile data / ora come nullable , puoi assegnargli solo un valore null. Quindi quello che stai cercando di fare è una delle due cose (potrebbe essercene di più ma posso solo pensare a due):

  • Assegna un valore minimo di data / ora alla tua variabile se non ne hai un valore. Puoi anche assegnare un valore di data / ora massimo, a seconda del modo che preferisci. Assicurati solo di essere coerente in tutto il sito quando controlli i valori di data / ora. Decidi di usare min o max e segui.

  • Contrassegna la tua variabile data / ora come nullable . In questo modo è possibile impostare la variabile data / ora su null se non si dispone di una variabile.

Vorrei dimostrare il mio primo punto usando un esempio. Il tipo di variabile DateTime non può essere impostato su null, ha bisogno di un valore, in questo caso lo imposterò sul valore minimo di DateTime se non c'è valore .

Il mio scenario è che ho una classe BlogPost . Ha molti campi / proprietà diversi ma ho scelto di usarne solo due per questo esempio. DatePublished è quando il post è stato pubblicato sul sito Web e deve contenere un valore di data / ora. DateModified è quando un post viene modificato, quindi non deve contenere un valore, ma può contenere un valore.

public class BlogPost : Entity
{
     public DateTime DateModified { get; set; }

     public DateTime DatePublished { get; set; }
}

Utilizzando ADO.NET per ottenere i dati dal database (assegnare DateTime.MinValue se non c'è valore):

BlogPost blogPost = new BlogPost();
blogPost.DateModified = sqlDataReader.IsDBNull(0) ? DateTime.MinValue : sqlDataReader.GetFieldValue<DateTime>(0);
blogPost.DatePublished = sqlDataReader.GetFieldValue<DateTime>(1);

Puoi raggiungere il mio secondo punto contrassegnando il campo DateModified come nullable . Ora puoi impostarlo su null se non esiste alcun valore per esso:

public DateTime? DateModified { get; set; }

Utilizzando ADO.NET per ottenere i dati dal database, sembrerà un po 'diverso dal modo in cui è stato fatto in precedenza (assegnando null invece di DateTime.MinValue ):

BlogPost blogPost = new BlogPost();
blogPost.DateModified = sqlDataReader.IsDBNull(0) ? (DateTime?)null : sqlDataReader.GetFieldValue<DateTime>(0);
blogPost.DatePublished = sqlDataReader.GetFieldValue<DateTime>(1);

Spero che questo aiuti a chiarire qualsiasi confusione. Dato che la mia risposta è circa 8 anni dopo, probabilmente ora sei un programmatore esperto in C # :)

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top