Das Objekt mit dem Wert "null" braucht einen Wert

189

Die Beschreibung der Ausnahme enthält ein Paradoxon: Nullbares Objekt muss einen Wert haben (?!)

Das ist das Problem:

Ich habe eine DateTimeExtendedKlasse, die hat

{
  DateTime? MyDataTime;
  int? otherdata;

}

und ein Konstruktor

DateTimeExtended(DateTimeExtended myNewDT)
{
   this.MyDateTime = myNewDT.MyDateTime.Value;
   this.otherdata = myNewDT.otherdata;
}

diesen Code ausführen

DateTimeExtended res = new DateTimeExtended(oldDTE);

wirft eine InvalidOperationExceptionmit der Nachricht:

Das Objekt mit dem Wert "null" braucht einen Wert.

myNewDT.MyDateTime.Value- ist gültig und enthält ein reguläres DateTimeObjekt.

Was bedeutet diese Nachricht und was mache ich falsch?

Beachten Sie, dass dies oldDTEnicht der Fall ist null. Ich habe das Valuevon entfernt, myNewDT.MyDateTimeaber die gleiche Ausnahme wird aufgrund eines generierten Setzers ausgelöst.

Dani
quelle
Was ist der andere Konstruktor?
Paul Creasey
Seltsam. Ich reproduziere die Ausnahme mit dem .Wert dort und erhalte dort keine Ausnahme ohne den .Wert. Sind Sie sicher, dass Sie den aktualisierten Code ausführen?
Yuliy
Der Konstruktor nimmt eine Instanz von sich. Wie erstellen Sie diese erste Instanz?
Paul Creasey
Es wird als new () ohne Parameter erstellt, und dann füge ich die Werte hinzu (es funktioniert).
Dani
6
Problem gelöst - das Problem war nicht da ... es gab einen generierten Setter für die otherdata und MyDateTime, der den Wert vor dem Setzen überprüfte. Fliegen, wenn es null ist !!!
Dani

Antworten:

201

Sie sollten die Zeile this.MyDateTime = myNewDT.MyDateTime.Value;auf einfach ändernthis.MyDateTime = myNewDT.MyDateTime;

Die Ausnahme, die Sie erhalten haben, wurde in die .ValueEigenschaft der Nullable geworfen DateTime , da eine Rückgabe erforderlich ist DateTime(da dies im Vertrag für .ValueStaaten festgelegt ist). Dies ist jedoch nicht möglich, da keine DateTimeRückgabe möglich ist. Daher wird eine Ausnahme ausgelöst .

Im Allgemeinen ist es eine schlechte Idee, blind .Valueeinen nullbaren Typ aufzurufen , es sei denn, Sie haben Vorkenntnisse darüber, dass diese Variable einen Wert enthalten MUSS (dh durch eine .HasValuePrüfung).

BEARBEITEN

Hier ist der Code dafür DateTimeExtended, der keine Ausnahme auslöst:

class DateTimeExtended
{
    public DateTime? MyDateTime;
    public int? otherdata;

    public DateTimeExtended() { }

    public DateTimeExtended(DateTimeExtended other)
    {
        this.MyDateTime = other.MyDateTime;
        this.otherdata = other.otherdata;
    }
}

Ich habe es so getestet:

DateTimeExtended dt1 = new DateTimeExtended();
DateTimeExtended dt2 = new DateTimeExtended(dt1);

Das Hinzufügen der .Valueauf other.MyDateTimeeine Ausnahme verursacht. Durch das Entfernen wird die Ausnahme beseitigt. Ich denke, Sie suchen am falschen Ort.

Yuliy
quelle
Sie haben Recht mit dem Wert, aber etwas anderes verursacht die Ausnahme. Ich habe den .value entfernt und die Codereihenfolge des Konstruktors geändert. Zuerst wird der int-Wert kopiert, aber dieselbe Ausnahme wird ausgelöst.
Dani
Ich habe die Frage kommentiert - das Problem gefunden, es war in einem generierten Setter für die Eigenschaften.
Dani
Ja, es hat mein Problem gelöst. Ich ändere einfach ein nullfähiges Objekt in ein nicht nullfähiges Objekt und konvertiere datetime direkt in einen String, nicht von datetimeobject.value.datetime.tostring ()
adnan
Gute Antwort. Es .Valueist sinnvoll, eine Ausnahme zu erhalten, die ein Null-Objekt aufruft (glaube ich), aber die Ausnahmemeldung ist wirklich irreführend, wenn Sie sich zufällig mit zwei Nullable-Objekten befassen. Etwas wie 'Die .Value-Eigenschaft erfordert, dass das Objekt nicht null ist' wäre viel sinnvoller.
DVK
9

Wenn LINQ - Erweiterungsmethoden (zB Select, Where), kann die Lambda - Funktion zu SQL umgewandelt werden , die nicht identisch mit C # -Code verhalten könnte. Zum Beispiel wird der Kurzschluss von C # ausgewertet &&und ||in SQLs eifrige ANDund konvertiert OR. Dies kann zu Problemen führen, wenn Sie in Ihrem Lambda nach Null suchen.

Beispiel:

MyEnum? type = null;
Entities.Table.Where(a => type == null || 
    a.type == (int)type).ToArray();  // Exception: Nullable object must have a value
Beschützer eins
quelle
5
Mir ist klar, dass diese Antwort für den speziellen Fall des OP nicht relevant ist, aber für die Ausnahme, die er erhält. Außerdem ist diese Seite der erste Treffer bei Google für diese Ausnahme, wodurch sie relevant wird.
Beschützer ein
6

Versuchen Sie, das fallen zu lassen .value

DateTimeExtended(DateTimeExtended myNewDT)
{
   this.MyDateTime = myNewDT.MyDateTime;
   this.otherdata = myNewDT.otherdata;
}
Paul Creasey
quelle
hilft nicht. es löst die gleiche Ausnahme aus, wenn ich zuerst die 2. Zeile starte.
Dani
2

In diesem Fall ist oldDTE null. Wenn Sie also versuchen, auf oldDTE.Value zuzugreifen, wird die InvalidOperationException ausgelöst, da kein Wert vorhanden ist. In Ihrem Beispiel können Sie einfach Folgendes tun:

this.MyDateTime = newDT.MyDateTime;
Lee
quelle
Das oldDTE ist nicht null, aber ich habe den Wert trotzdem entfernt ... es löst immer noch diese Ausnahme aus ...
Dani
1

Weisen Sie die Mitglieder direkt ohne das .ValueTeil zu:

DateTimeExtended(DateTimeExtended myNewDT)
{
   this.MyDateTime = myNewDT.MyDateTime;
   this.otherdata = myNewDT.otherdata;
}
Cecil hat einen Namen
quelle
0

Sieht so aus, als ob oldDTE.MyDateTime null war, also hat der Konstruktor versucht, den Wert zu übernehmen - was geworfen hat.

Pavel Radzivilovsky
quelle
0

Ich habe diese Meldung erhalten, als ich versucht habe, auf Werte eines Objekts mit Nullwert zuzugreifen.

sName = myObj.Name;

Dies führt zu Fehlern. Zuerst sollten Sie prüfen, ob das Objekt nicht null ist

if(myObj != null)
  sName = myObj.Name;

Das funktioniert.

Juris
quelle
1
Versuchen Sie vor der Beantwortung zunächst, die anderen Antworten auf die Frage durchzulesen - insbesondere die akzeptierte Antwort, in der genau angegeben ist, was Sie in Ihre Antwort eingefügt haben. Obwohl es nicht mit Code angezeigt wird, wird es buchstabiert. Versuchen Sie auch, Ihren Beispielcode für die Frage relevant zu machen - wie zum Beispiel this.MyDateTime = myNewDT.MyDateTime.Value;nichtsName = myObj.Name;
newfurniturey