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.


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.


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

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

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;

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

0

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


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.


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
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.