Hallo,
ich habe folgende Frage. Visual Studio 2022 meckert in der unten stehenden Zeile gleich zwei Male:
ds.Tables["Artikel"].PrimaryKey = new DataColumn[1] { ArtikelColumns["NUMMER"] };
Bei "ds.Tables["Artikel"].PrimaryKey" meldet VS: Mögliche Nullverweiszuweisung
und bei "ArtikelColumns["NUMMER"]": Dereferenzierung eines möglichen Nullverweises
Die grün unterwellten Stellen habe ich hier unterstrichen.
Ich weiß aber, dass dies nicht vorkommen kann, daher schalte ich diese Warnungen für die Zeile ab:
#pragma warning disable CS8601, CS8602 // Mögliche Nullverweiszuweisung bzw. Dereferenzierung eines möglichen Nullverweises
ds.Tables["Artikel"].PrimaryKey = new DataColumn[1] { ArtikelColumns["NUMMER"] };
#pragma warning restore CS8602, CS8601
Nicht schön, aber zunächst egal.
Nun es ist so, dass an vielen Stellen VS Warnungen unterbindet, wenn man davor eine Prüfung macht. Daher habe ich testhalber folgenden (hässlichen) Code getestet:
if (ds != null && ds.Tables != null || ds?.Tables?["Artikel"] != null && ArtikelColumns["NUMMER"] != null)
{
ds.Tables["Artikel"].PrimaryKey = new DataColumn[1] { ArtikelColumns["NUMMER"] };
}
Es hat sich aber nichts geändert.
Versagt hier IntelliSense oder mache ich grundsätzlich was falsch und ich merke es nur nicht?
Liebe Grüße
René
René
Deine Prüfung macht auch wenig Sinn, wenn ds != null geht er schon rein. ds.Tables["Artikel"] kann ja immer noch fehlen.
Deine Prüfung macht auch wenig Sinn, wenn ds != null geht er schon rein. ds.Tables["Artikel"] kann ja immer noch fehlen.
Ja, hast du Recht, sorry. Ich habe nun die Abfrage über die Zwischenablage kopiert, um keinen doofen Fehler mehr zu machen:
if (ds == null || ds.Tables == null || ds.Tables["Artikel"] == null || ArtikelColumns["NUMMER"] == null)
{
ds.Tables["Artikel"].PrimaryKey = new DataColumn[1] { ArtikelColumns["NUMMER"] };
}
Es ändert sich jedoch nichts (siehe Bild in der Dateianlage).
LG
René
René
Hallo ihr beiden,
jetzt ist die Abfrage ja genau falsch herum, es müsste doch so aussehen:
if (ds != null && ds.Tables != null && ds.Tables["Artikel"] != null && ArtikelColumns["NUMMER"] != null)
Aber müsste zumindestens für die erste Warnung nicht einfach der ?.
-Operator reichen?
ds?.Tables["Artikel"]?.PrimaryKey = ...
Bei der zweiten kommt es darauf an, wie ArtikelColumns
definiert und zugewiesen ist.
Ich denke, gemeint ist, daß diese Variable selbst null
sein kann, daher entweder auch auf ArtikelColumns != null
prüfen oder
new DataColumn[1] { ArtikelColumns?["NUMMER"]};
Dann kann jedoch danach null
als Wert in dem DataColumn
-Array stehen.
jetzt ist die Abfrage ja genau falsch herum, es müsste doch so aussehen:
if (ds != null && ds.Tables != null && ds.Tables["Artikel"] != null && ArtikelColumns["NUMMER"] != null)
Um Gottes Willen! Ich freue mich auf Weihnachten – ein paar Feiertage werden mir gut tun.
Dennoch ändert sich an den zwei Warnungen nichts. Es ist auch nicht ganz wichtig, denn ich weiß schon (vorher geprüft), dass alles korrekt ist. Daher:
#pragma warning disable CS8601, CS8602 // Mögliche Nullverweiszuweisung bzw. Dereferenzierung eines möglichen Nullverweises
ds.Tables["Artikel"].PrimaryKey = new DataColumn[1] { ArtikelColumns["NUMMER"] };
#pragma warning restore CS8602, CS8601
Dennoch würde ich gerne wissen, warum VS das als Warnung einstuft.
Aber müsste zumindestens für die erste Warnung nicht einfach der
?.
-Operator reichen?ds?.Tables["Artikel"]?.PrimaryKey = ...
Geht nicht: "Die linke Seite einer Zuweisung muss eine Variable, eine Eigenschaft oder ein Indexer sein"
Bei der zweiten kommt es darauf an, wie
ArtikelColumns
definiert und zugewiesen ist.
Ich denke, gemeint ist, daß diese Variable selbstnull
sein kann, daher entweder auch aufArtikelColumns != null
prüfen odernew DataColumn[1] { ArtikelColumns?["NUMMER"]};
Dann kann jedoch danach
null
als Wert in demDataColumn
-Array stehen.
Auch schon getestet, aber es ändert sich weiterhin nichts.
Danke und lG
René
René
Stimmt, der zweite ?.
-Operator gibt (leider) diese Fehlermeldung. Also doch
var table = ds?.Tables["Artikel"];
if (table != null)
table.PrimaryKey = ...;
Und auch bei der zusätzlichen Abfrage
if (ArtikelColumns != null)
... = new DataColumn[1] { ArtikelColumns["NUMMER"] };
kommt immer noch die Warnung CS8602?
Dann wird es daran liegen, daß diese DataColumn
eben null
sein kann - also auch hier
var dataColumn = ArtikelColumns["NUMMER"];
if (dataColumn != null)
... = new DataColumn[1] { dataColumn };
Wenn du dir sicher bist, daß zur Laufzeit niemals null
herauskommt (bzw. eben eine mögliche NullReferenceException
in Kauf nimmst), dann kannst du die Warnungen abschalten, anstatt den komplexeren Code zu schreiben.
Der Compiler kann ja nicht wissen, ob die Einträge "Artikel"
bzw. "NUMMER"
wirklich zur Laufzeit existieren, daher wohl die Warnungen.
Und zwischen den Aufrufen könnte sich ja auch der Wert geändert.
Bei der Prüfung nicht null, aber dann bei der Zuweisung.
Hier bietet sich ggf. die Verwendung des ! (null-forgiving) operator (C# reference) an,
wenn sichergestellt ist das der Wert nicht null ist.
null-forgiving ist eigentlich wirklich nur für konzeptionelle Dinge gedacht, bei denen man (noch) kein anderen Weg nutzen kann.
Beispiele sind da Linq-Queries, Modell Conventions (zB EF Core)....
- performance is a feature -
Microsoft MVP - @Website - @AzureStuttgart - github.com/BenjaminAbt - Sustainable Code
Hallo Th69,
in jeder erdenklichen Kombination werden beide Warnungen ausgegeben. Wie gesagt, an dieser Stelle nicht schlimm, denn ich weiß, dass alles OK ist. Daher habe ich nur für die betroffene Zeile diese Compilerwarnungen deaktiviert:
#pragma warning disable CS8601, CS8602 // Mögliche Nullverweiszuweisung bzw. Dereferenzierung eines möglichen Nullverweises
ds.Tables["Artikel"].PrimaryKey = new DataColumn[1] { ArtikelColumns["NUMMER"] };
#pragma warning restore CS8602, CS8601
Nicht schlimm, mich hatte nur interessiert, warum der Compiler an dieser Stelle so beharrlich ist.
Danke und Grüße
René
René
Hier bietet sich ggf. die Verwendung des
> an,
wenn sichergestellt ist das der Wert nicht null ist.
Danke! Wie sagte eine berühmte Fernsehdame? "Hier werden Sie geholfen!"
Du kannst lachen, aber ich kannte diesen Postfixoperator nicht. Mit dem kann ich an der besagten Stelle in der Tat, die Compilerwarnung abschalten:
ds.Tables["Artikel"]!.PrimaryKey = new DataColumn[1] { ArtikelColumns["NUMMER"]! }
Ob das aber sicher und übersichtlicher als die zwei hässlichen #pragma-Zeilen ist, bin ich mir noch nicht ganz im Klaren – wahrscheinlich aber ja, denn in beiden Fällen würde das Programm genau an dieser Stelle eine Ausnahme werfen, wenn meine Behauptung der vollkommenen Korrektheit nicht zutreffend wäre.
@Abt
Wenn ich Microsoft https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/operators/null-forgiving?WT.mc_id=DT-MVP-5001507 richtig verstehe, kann ich durchaus diesen Postfixoperator für meinen Zweck nutzen:
You can also use the null-forgiving operator when you definitely know that an expression can't be null but the compiler doesn't manage to recognize that. In the following example, if the IsValid method returns true, its argument isn't null and you can safely dereference it:
Sehr interessant, denn ich habe durch eure Hilfe was neues gelernt.
Vielen Dank und einen erfolgreichen Start in die neue Woche!
LG
René
René
Dein Fall ist anders als der aus den Docs, damit auch der Code - ergo hinkt der Vergleich.
Im Endeffekt hast Du einen Folgefehler im Code, den viele spüren, wenn sie plötzlich mit Null Warnings konfrontiert werden.
In Deinem Code prüfst Du eine Referenz, ob sie existiert: zB
ds.Tables["Artikel"] != null
und an weiter Stelle machst Du exakt das gleiche, nur dies mal nicht als Vergleich sondern als Zuweisung
ds.Tables["Artikel"].PrimaryKey = .... // das hier gibt eine Compiler Warnung
Das war a) schon immer ineffizient, weil Du hier mehrfach das Zeug von Tables über den Index holen musst und b) ist zusätzlich jetzt halt doof wegen Compiler Warnings, die zurecht erfolgen.
Für a) gab es schon immer die Lösung, dass man eben Dont Repeat Yourself beachtet und solch eine Abfrage in eine Variable auslagert
DataTable? dt = ds.Tables["Artikel"];
if(dt is not null)
{
dt.PrimaryKey = .... // das hier gibt kein Compiler Warning, da der Compiler erkennt, dass dt hier auf null geprüft wurde
}
Das ist im Vergleich viel sauber und viel effizienter. Das kostet tatsächlich im realen Leben auch weniger CPU-Leistung.
Hättest die Grundregel von DRY befolgt, gäbe es nebenbei diesen Effekt gar nicht 😉
Mit Pattern Matching ist das mittlerweile auch einfacher / aka "schicker" umsetzen
if (ds?.Tables is DataTableCollection tables && tables["Artikel"] is DataTable articleTable)
{
articleTable.PrimaryKey = new DataColumn[1] { .. gleiches Prinzip für Data Column };
}
Null Forgiving hat wirklich einen anderen Use Case als schmutzigen Code zu verstecken 😉
- performance is a feature -
Microsoft MVP - @Website - @AzureStuttgart - github.com/BenjaminAbt - Sustainable Code