Laden...

NullReferenceException trotz .HasValue ???

Erstellt von sra vor 14 Jahren Letzter Beitrag vor 14 Jahren 1.475 Views
S
sra Themenstarter:in
230 Beiträge seit 2004
vor 14 Jahren
NullReferenceException trotz .HasValue ???

Hallo ihr

Ich zweifle grade grundlegend an meinem Verständnis von nullable Types (für euch csharper, so nennt man die Typen mit dem "?" hinten dran).

Folgendes dachte ich, müsste doch funktionieren (sorry für das VB).

Im Code behind habe ich einige Public Member initialisiert (natürlich ausserhalb irgendwelcher Methoden):

Public Einwohner() As Nullable(Of Decimal) = {0, 0, 0, 0, 0}

Im Page_Load fülle ich diese mit dem Resultat eines Linq Queries:

Einwohner(0) = (From p In kopfdaten Where p.kon_Konto = 810 And p.p.bmk_jah_Jahr = Year - 5 Select p.p.bmk_Betrag).Sum()

Das kann zugegebenermassen null ergeben, da unter umständen für das abgefragte Jahr keine Daten vorhanden sind.

In aspx greife ich auf den Public Member dann zu, wobei ich extra HasValue abfrage:

<td class="tdNormal" style="width:80px; text-align:right;"><%=IIf(Einwohner(0).HasValue, Einwohner(0).Value.ToString("n0"), "-")%></td>

Trotzdem kriege ich an dieser Stelle eine NullReferenceException.

Was habe ich nicht (oder falsch) verstanden?

Gruss
sra

Edit: Evt ist es fürs bessere Verständnis nötig zu erwähnen, dass der iif Befehl quasi das equivalent zum ?: Operator in csharp ist.

Wenn Zeit in Geschichte übergeht und keine Blüten trägt werden Zukunftsbilder blass //Clueso

5.742 Beiträge seit 2007
vor 14 Jahren

Hallo sra,

generell siehe [FAQ] NullReferenceException: Der Objektverweis wurde nicht auf eine Objektinstanz festgelegt

Eventuell ist ja auch Einwohner null.

S
sra Themenstarter:in
230 Beiträge seit 2004
vor 14 Jahren

Einwohner(i) wird erwartungsgemäss ab und zu mal null zurückgeben, wenn für das Jahr keine Daten erfasst sind. Deshalb habe ich das Ding auch als Nullable deklariert (decimal?) und frage bei der Ausgabe des Wertes .HasValue ab.

Im von dir empfohlenen Artikel kann ich nichts über Nullable Types lesen.

Wenn Zeit in Geschichte übergeht und keine Blüten trägt werden Zukunftsbilder blass //Clueso

5.941 Beiträge seit 2005
vor 14 Jahren

Hallo sra

Du deklarierst mit:


Dim Einwohner() As Nullable(Of Decimal)

einen Array von Nullable(Of Decimal).

In C# entspricht das:


decimal?[] einwohner;

Da Array ein Referenztyp ist, kann er null sein.
In deinem Fall ist der Array null und darum kriegst du auch deine Exception, was im Link von winSharp93 oder mithilfe des Debuggers auch ersichtlich geworden wäre.

Es knallt genau an der Stelle wo du das erste Mal auf einen Eintrag im Array zugreifst, also bei deiner HasValue-Abfrage.

Du müsstest also deinen Array auf null prüfen und erst dann weiter machen oder es nie dazu kommen lassen das er null ist, je nach Situation.

Gruss Peter

--
Microsoft MVP - Visual Developer ASP / ASP.NET, Switzerland 2007 - 2011

S
sra Themenstarter:in
230 Beiträge seit 2004
vor 14 Jahren

Hallo Peter

Danke schonmal für die Antwort.

Ich glaube, dass mein Denkfehler hier ist (so stelle ich mir das vor):

Das Array müsste doch für die ersten 5 Positionen einen Wert haben, da es direkt beim Deklarieren auch initialisiert wird.

decimal?[] einwohner = { 0, 0, 0, 0, 0 };

Wenn ich nun im Page_Load den Wert des Arrays an der Position [0] mit einem "nulligen decimal" (also null, aber innerhalb eines nullable decimal) überschreibe, dann müsste imho das Array an dieser Position noch immer "vorhanden sein", der Wert des Inhaltes müsste an dieser Position dann einfach null sein.

naja.. Ganz offensichtlich verhält es sich hier anders.
Sorry wenn ich mich bisschen schwer tue, aber im Moment blicke ich nicht 100% durch.

Wie checke ich denn, ob das Array (das übrigens in diesem Falle für die Positionen 2-5 Werte hat) an dieser Stelle überhaupt einen Wert hat?

Gruss
sra

Edit: Betrachte es als "unwissendes Stochern im Dunkel", aber folgendes bringt nach wie vor eine NullReferenceException:

Not Einwohner(0) = Nothing AndAlso Einwohner(0).HasValue

Wenn Zeit in Geschichte übergeht und keine Blüten trägt werden Zukunftsbilder blass //Clueso

K
593 Beiträge seit 2007
vor 14 Jahren

Hallo sra,

ich kann nicht ganz nachvollziehen was du dort schreibst aber der unterschied zwischen:


null und 0

ist schon klar oder? Den das nullable bedeutert dort das der wert auch


null

sein darf. Somit keinen bestimmten wert. 0 Ist ein estimmter Wert. Daher ein denkfehler? (P.S. Ich hoffe ich hab jetzt kein quark geredet...^^ )

EDIT: Achja weitergehend würde ich behaupten das du bei dem Zugriff eine NullReferenceExeption bekommst weil es nicht initialisiert bzw das Objekt keine Werte hat, kannst du das mit dem Debugger checken?

Viele Grüße

Kaji

5.941 Beiträge seit 2005
vor 14 Jahren

Hallo sra

Also ich kann das nicht nachvollziehen.
So wie du das hier schilderst müsste das klappen.

Wie schon im verlinkten Artikel beschrieben, ist es für uns unmöglich dir da weiterzuhelfen, ohne vor dem Projekt zu sitzen.

Der Fehler liegt mit ziemlicher Sicherheit an einem Teil der du uns noch nicht gezeigt hast, oder an einem Umstand den wir nicht kennen 😃.

Darum benutze bitte den Debugger und geh auf die Suche damit.

Gruss Peter

--
Microsoft MVP - Visual Developer ASP / ASP.NET, Switzerland 2007 - 2011

S
sra Themenstarter:in
230 Beiträge seit 2004
vor 14 Jahren

Manchmal muss man sich zum Affen machen um danach trotzdem nicht schlauer zu sein. Schlussendlich habe ich am völlig falschen Ort nach dem Fehler gesucht, und schlussendlich verstehe ich wie es zum Fehler kam nach wie vor nicht.

Die Lösung: Wenn ich die Zeile mit dem Iif(...) wo ich den Wert ausgebe ersetze mit einem normalen If ... Else, dann funktioniert das Ganze tadellos.

<%If (Einwohner(0).HasValue) Then Response.Write(Einwohner(0).Value.ToString("n0")) Else Response.Write("-")%>

Meiner Meinung nach sollte der Code genau dasselbe bewirken wie mein erstes Beispiel

<%=IIf(Einwohner(0).HasValue, Einwohner(0).Value.ToString("n0"), "-")%>

Vielleicht weiss ja noch einer aus dem Handgreif wieso das nicht klappt wie ich es ursprünglich wollte, aber das ist jetzt nicht derart wichtig.

Gruss und vielen Dank für die Hilfe
sra

Wenn Zeit in Geschichte übergeht und keine Blüten trägt werden Zukunftsbilder blass //Clueso

5.941 Beiträge seit 2005
vor 14 Jahren

Hallo sra

Hier die Erklärung:

War mir nicht bewusst, obwohl ich iif kannte 😉

Gruss Peter

--
Microsoft MVP - Visual Developer ASP / ASP.NET, Switzerland 2007 - 2011

5.299 Beiträge seit 2008
vor 14 Jahren

IIF ist doch auch untypisiert, gibt also nur Type Object zurück. Das ist doch eh voll unsauber, so zu proggen, nämlich ohne Option Strict.

Seit 2008 gibtes das Immediate If in VB, das ist typisiert, und ein SprachFeature mit abkürzender Auswertung (nur der Treffer-Zweig wird ausgewertet). Probierma


<%=If(Einwohner(0).HasValue, Einwohner(0).Value.ToString("n0"), "-")%>

mach Option Strict On, und vergiß IIf.

(PS: kann natürlich sein, ich voll auf Holzweg, da ich in ASP.Net kaum durchblick)

Der frühe Apfel fängt den Wurm.