Was ist die beste Vorgehensweise bei der Rückgabe von Daten aus Funktionen ? Ist es besser, eine Null oder ein leeres Objekt zurückzugeben? Und warum sollte man eins über das andere tun?
Bedenken Sie:
public UserEntity GetUserById(Guid userId)
{
//Imagine some code here to access database.....
//Check if data was returned and return a null if none found
if (!DataExists)
return null;
//Should I be doing this here instead?
//return new UserEntity();
else
return existingUserEntity;
}
Stellen wir uns vor, dass es in diesem Programm gültige Fälle gibt, in denen keine Benutzerinformationen mit dieser GUID in der Datenbank vorhanden sind. Ich würde mir vorstellen, dass es in diesem Fall nicht angebracht wäre, eine Ausnahme zu machen? Ich habe auch den Eindruck, dass die Behandlung von Ausnahmen die Leistung beeinträchtigen kann.
c#
.net
function
return-value
7wp
quelle
quelle
if (!DataExists)
.Antworten:
Die Rückgabe von null ist normalerweise die beste Idee, wenn Sie angeben möchten, dass keine Daten verfügbar sind.
Ein leeres Objekt impliziert, dass Daten zurückgegeben wurden, während die Rückgabe von null eindeutig anzeigt, dass nichts zurückgegeben wurde.
Darüber hinaus führt die Rückgabe einer Null zu einer Null-Ausnahme, wenn Sie versuchen, auf Mitglieder im Objekt zuzugreifen. Dies kann hilfreich sein, um fehlerhaften Code hervorzuheben. Der Versuch, auf ein Mitglied von nichts zuzugreifen, macht keinen Sinn. Der Zugriff auf Mitglieder eines leeren Objekts schlägt nicht fehl, was bedeutet, dass Fehler unentdeckt bleiben können.
quelle
bool GetUserById(Guid userId, out UserEntity result)
den ich dem Rückgabewert "null" vorziehen würde und der nicht so extrem ist wie das Auslösen einer Ausnahme. Es erlaubt schön-null
freien Code wieif(GetUserById(x,u)) { ... }
.Es kommt darauf an, was für Ihren Fall am sinnvollsten ist.
Ist es sinnvoll, null zurückzugeben, z. B. "kein solcher Benutzer existiert"?
Oder ist es sinnvoll, einen Standardbenutzer zu erstellen? Dies ist am sinnvollsten, wenn Sie davon ausgehen können, dass der aufrufende Code, wenn ein Benutzer NICHT existiert, beabsichtigt, dass einer existiert, wenn er danach fragt.
Oder ist es sinnvoll, eine Ausnahme (a la "FileNotFound") auszulösen, wenn der aufrufende Code einen Benutzer mit einer ungültigen ID fordert?
Unter dem Gesichtspunkt der Trennung von Bedenken / SRP sind die ersten beiden jedoch korrekter. Und technisch gesehen ist die erste die korrekteste (aber nur durch ein Haar) - GetUserById sollte nur für eine Sache verantwortlich sein - den Benutzer zu bekommen. Die Behandlung eines eigenen Falls "Benutzer existiert nicht" durch Rückgabe von etwas anderem könnte eine Verletzung von SRP darstellen. Trennung in eine andere Prüfung -
bool DoesUserExist(id)
wäre angemessen, wenn Sie eine Ausnahme auslösen möchten.Basierend auf ausführlichen Kommentaren unten : Wenn es sich um eine Entwurfsfrage auf API-Ebene handelt, kann diese Methode analog zu "OpenFile" oder "ReadEntireFile" sein. Wir "öffnen" einen Benutzer aus einem Repository und hydratisieren das Objekt aus den resultierenden Daten. In diesem Fall könnte eine Ausnahme angebracht sein. Es könnte nicht sein, aber es könnte sein.
Alle Ansätze sind akzeptabel - es kommt nur darauf an, basierend auf dem größeren Kontext der API / Anwendung.
quelle
Persönlich benutze ich NULL. Es wird deutlich, dass keine Daten zurückgegeben werden müssen. Es gibt jedoch Fälle, in denen ein Nullobjekt nützlich sein kann.
quelle
Wenn Ihr Rückgabetyp ein Array ist, geben Sie ein leeres Array zurück, andernfalls geben Sie null zurück.
quelle
null
. Sie können es inforeach
Anweisungen und Linq-Abfragen verwenden, ohne sich Sorgen machen zu müssenNullReferenceException
.Sie sollten (nur) eine Ausnahme auslösen, wenn ein bestimmter Vertrag gebrochen ist.
Wenn Sie in Ihrem speziellen Beispiel nach einer UserEntity fragen, die auf einer bekannten ID basiert, hängt dies davon ab, ob fehlende (gelöschte) Benutzer erwartet werden. Wenn ja, kehren Sie zurück,
null
aber wenn dies kein erwarteter Fall ist, lösen Sie eine Ausnahme aus.Beachten Sie, dass die aufgerufene Funktion
UserEntity GetUserByName(string name)
wahrscheinlich nicht werfen, sondern null zurückgeben würde. In beiden Fällen wäre die Rückgabe einer leeren UserEntity nicht hilfreich.Bei Strings, Arrays und Sammlungen ist die Situation normalerweise anders. Ich erinnere mich an einige Richtlinien aus MS, die Methoden
null
als "leere" Liste akzeptieren sollten, aber Sammlungen mit der Länge Null zurückgeben solltennull
. Das gleiche gilt für Strings. Beachten Sie, dass Sie leere Arrays deklarieren können:int[] arr = new int[0];
quelle
.Wher(p => p.Lastname == "qwerty")
sollte eine leere Sammlung zurückgeben, nichtnull
.Dies ist eine Geschäftsfrage, die davon abhängt, ob die Existenz eines Benutzers mit einer bestimmten Guid-ID ein erwarteter normaler Anwendungsfall für diese Funktion ist oder ob es sich um eine Anomalie handelt, die verhindert, dass die Anwendung die Funktion, die diese Methode dem Benutzer bereitstellt, erfolgreich ausführt Objekt zu ...
Wenn es sich um eine "Ausnahme" handelt, verhindert die Abwesenheit eines Benutzers mit dieser ID, dass die Anwendung die von ihr ausgeführte Funktion erfolgreich ausführt. (Angenommen, wir erstellen eine Rechnung für einen Kunden, an den wir das Produkt versendet haben ... ), dann sollte diese Situation eine ArgumentException (oder eine andere benutzerdefinierte Ausnahme) auslösen.
Wenn ein fehlender Benutzer in Ordnung ist (eines der möglichen normalen Ergebnisse beim Aufrufen dieser Funktion), geben Sie eine Null zurück ....
EDIT: (um den Kommentar von Adam in einer anderen Antwort anzusprechen)
Wenn die Anwendung mehrere Geschäftsprozesse enthält, von denen einer oder mehrere einen Benutzer benötigen, um erfolgreich abgeschlossen zu werden, und einer oder mehrere ohne einen Benutzer erfolgreich abgeschlossen werden können, sollte die Ausnahme weiter oben im Aufrufstapel ausgelöst werden, näher an der Stelle Die Geschäftsprozesse, für die ein Benutzer erforderlich ist, rufen diesen Ausführungsthread auf. Methoden zwischen dieser Methode und dem Punkt (an dem die Ausnahme ausgelöst wird) sollten lediglich mitteilen, dass kein Benutzer vorhanden ist (null, boolesch, was auch immer - dies ist ein Implementierungsdetail).
Aber wenn alle Prozesse in der Anwendung einen Benutzer erfordern , würde ich trotzdem die Ausnahme in dieser Methode auslösen ...
quelle
Ich persönlich würde null zurückgeben, da ich so erwarten würde, dass die DAL / Repository-Schicht funktioniert.
Wenn es nicht existiert, geben Sie nichts zurück, was als erfolgreiches Abrufen eines Objekts ausgelegt werden könnte.
null
hier wunderbar.Das Wichtigste ist, dass Sie über Ihre DAL / Repos-Ebene hinweg konsistent sind, damit Sie nicht verwirrt sind, wie Sie sie verwenden.
quelle
Ich neige dazu
return null
wenn die Objekt-ID nicht existiert, wenn vorher nicht bekannt ist, ob dies der Fall sein soll vorhanden sein.throw
Wenn die Objekt-ID nicht vorhanden ist, sollte sie vorhanden sein.Ich unterscheide diese beiden Szenarien mit diesen drei Arten von Methoden. Zuerst:
Zweite:
Dritte:
quelle
out
nichtref
Ein weiterer Ansatz besteht darin, ein Rückrufobjekt oder einen Delegaten zu übergeben, der den Wert verarbeitet. Wird kein Wert gefunden, wird der Rückruf nicht aufgerufen.
Dies funktioniert gut, wenn Sie Nullprüfungen im gesamten Code vermeiden möchten und wenn das Nichtfinden eines Werts kein Fehler ist. Sie können auch einen Rückruf bereitstellen, wenn keine Objekte gefunden werden, wenn Sie eine spezielle Verarbeitung benötigen.
Der gleiche Ansatz mit einem einzelnen Objekt könnte folgendermaßen aussehen:
Aus gestalterischer Sicht gefällt mir dieser Ansatz sehr gut, aber er hat den Nachteil, dass die Anrufstelle in Sprachen, die erstklassige Funktionen nicht ohne weiteres unterstützen, umfangreicher wird.
quelle
Wir verwenden CSLA.NET und es wird die Ansicht vertreten, dass ein fehlgeschlagener Datenabruf ein "leeres" Objekt zurückgeben sollte. Dies ist eigentlich ziemlich ärgerlich, da es die Konvention
obj.IsNew
erfordert, zu prüfen, ob eher alsobj == null
.Wie bereits erwähnt, Null-Rückgabewerte dazu, dass der Code sofort fehlschlägt, wodurch die Wahrscheinlichkeit von Stealth-Problemen durch leere Objekte verringert wird.
Ich persönlich denke
null
eleganter.Es ist ein sehr häufiger Fall, und ich bin überrascht, dass die Leute hier davon überrascht zu sein scheinen: In jeder Webanwendung werden Daten häufig mithilfe eines Querystring-Parameters abgerufen, der offensichtlich entstellt werden kann, sodass der Entwickler Vorfälle von "nicht gefunden" verarbeiten muss ".
Sie könnten damit umgehen, indem Sie:
... aber das ist jedes Mal ein zusätzlicher Aufruf der Datenbank, was auf stark frequentierten Seiten ein Problem sein kann. Wohingegen:
... erfordert nur einen Anruf.
quelle
Ich bevorzuge
null
, da es mit dem Null-Coalescing-Operator (??
) kompatibel ist .quelle
Ich würde sagen, return null anstelle eines leeren Objekts.
Bei der hier erwähnten spezifischen Instanz suchen Sie nach einem Benutzer anhand der Benutzer-ID. Dies ist eine Art Schlüssel für diesen Benutzer. In diesem Fall möchte ich wahrscheinlich eine Ausnahme auslösen, wenn keine Benutzerinstanzinstanz gefunden wird .
Dies ist die Regel, die ich im Allgemeinen befolge:
quelle
Es hängt vom Kontext ab, aber ich gebe im Allgemeinen null zurück, wenn ich nach einem bestimmten Objekt suche (wie in Ihrem Beispiel), und eine leere Sammlung zurück, wenn ich nach einer Reihe von Objekten suche, aber keine.
Wenn Sie einen Fehler in Ihrem Code gemacht haben und die Rückgabe von null zu Nullzeigerausnahmen führt, ist es umso besser, je früher Sie dies erkennen. Wenn Sie ein leeres Objekt zurückgeben, funktioniert die erstmalige Verwendung möglicherweise, später werden jedoch möglicherweise Fehler angezeigt.
quelle
Die besten in diesem Fall geben "null" zurück, wenn es keinen solchen Benutzer gibt. Machen Sie Ihre Methode auch statisch.
Bearbeiten:
Normalerweise sind solche Methoden Mitglieder einer "Benutzer" -Klasse und haben keinen Zugriff auf ihre Instanzmitglieder. In diesem Fall sollte die Methode statisch sein, andernfalls müssen Sie eine Instanz von "User" erstellen und dann die GetUserById-Methode aufrufen, die eine weitere "User" -Instanz zurückgibt. Stimmen Sie zu, dass dies verwirrend ist. Wenn die GetUserById-Methode jedoch Mitglied einer "DatabaseFactory" -Klasse ist, ist es kein Problem, sie als Instanzmitglied zu belassen.
quelle
Ich persönlich gebe eine Standardinstanz des Objekts zurück. Der Grund ist, dass ich erwarte, dass die Methode Null zu Viele oder Null zu Eins zurückgibt (abhängig vom Zweck der Methode). Der einzige Grund, warum es sich bei diesem Ansatz um einen Fehlerzustand jeglicher Art handelt, besteht darin, dass die Methode keine Objekte zurückgegeben hat und dies immer erwartet wurde (in Form einer Eins-zu-Viele-Rückgabe oder einer einzelnen Rückgabe).
Die Annahme, dass dies eine Frage der Geschäftsdomäne ist, sehe ich von dieser Seite der Gleichung aus einfach nicht. Die Normalisierung von Rückgabetypen ist eine gültige Frage zur Anwendungsarchitektur. Zumindest unterliegt es einer Standardisierung der Codierungspraktiken. Ich bezweifle, dass es einen Geschäftsbenutzer gibt, der sagen wird "Geben Sie ihm in Szenario X einfach eine Null".
quelle
In unseren Business Objects haben wir zwei Haupt-Get-Methoden:
Um die Dinge im Kontext einfach zu halten oder Sie fragen, wären sie:
Die erste Methode wird beim Abrufen bestimmter Entitäten verwendet, die zweite Methode wird speziell beim Hinzufügen oder Bearbeiten von Entitäten auf Webseiten verwendet.
Dies ermöglicht es uns, das Beste aus beiden Welten in dem Kontext zu haben, in dem sie verwendet werden.
quelle
Ich bin ein französischer IT-Student, also entschuldigen Sie mein schlechtes Englisch. In unseren Klassen wird uns gesagt, dass eine solche Methode niemals null oder ein leeres Objekt zurückgeben sollte. Der Benutzer dieser Methode muss zuerst überprüfen, ob das gesuchte Objekt vorhanden ist, bevor er versucht, es abzurufen.
Mit Java werden wir gebeten, a hinzuzufügen
assert exists(object) : "You shouldn't try to access an object that doesn't exist";
am Anfang jeder Methode, die null zurückgeben könnte , um die "Vorbedingung" auszudrücken (ich weiß nicht, was das Wort auf Englisch ist).IMO ist das wirklich nicht einfach zu bedienen, aber das ist es, was ich benutze und auf etwas Besseres warte.
quelle
Wenn der Fall, dass der Benutzer nicht gefunden wird, häufig genug auftritt und Sie je nach den Umständen auf verschiedene Weise damit umgehen möchten (manchmal eine Ausnahme auslösen, manchmal einen leeren Benutzer ersetzen), können Sie auch etwas verwenden,
Option
das demMaybe
Typ von F # oder Haskell nahe kommt , der den Fall "kein Wert" explizit von "etwas gefunden!" trennt. Der Datenbankzugriffscode könnte folgendermaßen aussehen:Und so verwendet werden:
Leider scheint jeder einen eigenen Typ zu rollen.
quelle
Ich gebe normalerweise null zurück. Es bietet einen schnellen und einfachen Mechanismus, um zu erkennen, ob etwas schief gelaufen ist, ohne Ausnahmen zu werfen und überall Tonnen von Versuchen / Fangen zu verwenden.
quelle
Für Sammlungstypen würde ich eine leere Sammlung zurückgeben, für alle anderen Typen bevorzuge ich die Verwendung der NullObject-Muster für die Rückgabe eines Objekts, das dieselbe Schnittstelle wie die des zurückgebenden Typs implementiert. Einzelheiten zum Muster finden Sie im Linktext
Bei Verwendung des NullObject-Musters wäre dies: -
{// Stellen Sie sich hier Code vor, um auf die Datenbank zuzugreifen .....
}}
quelle
Um das, was andere gesagt haben, prägnanter auszudrücken ...
Ausnahmen gelten für außergewöhnliche Umstände
Wenn es sich bei dieser Methode um eine reine Datenzugriffsschicht handelt, würde ich sagen, dass bei einem Parameter, der in eine select-Anweisung aufgenommen wird, möglicherweise keine Zeilen gefunden werden, aus denen ein Objekt erstellt werden kann. Daher wäre die Rückgabe von null akzeptabel ist Datenzugriffslogik.
Wenn ich dagegen erwarten würde, dass mein Parameter einen Primärschlüssel widerspiegelt und ich nur eine Zeile zurückbekomme, würde ich eine Ausnahme auslösen, wenn ich mehr als eine zurückbekomme. 0 ist in Ordnung, um null zurückzugeben, 2 nicht.
Wenn ich einen Anmeldecode hätte, der gegen einen LDAP-Anbieter und dann gegen eine Datenbank geprüft wurde, um weitere Details zu erhalten, und ich erwartete, dass diese jederzeit synchron sein sollten, könnte ich dann die Ausnahme auslösen. Wie andere sagten, sind es Geschäftsregeln.
Jetzt werde ich sagen, dass dies eine allgemeine Regel ist. Es gibt Zeiten, in denen Sie das vielleicht brechen möchten. Meine Erfahrungen und Experimente mit C # (viel davon) und Java (ein bisschen davon) haben mich jedoch gelehrt, dass es in Bezug auf die Leistung viel teurer ist, Ausnahmen zu behandeln, als vorhersehbare Probleme über bedingte Logik zu behandeln. Ich spreche von 2 oder 3 Größenordnungen, die in einigen Fällen teurer sind. Wenn es also möglich ist, dass Ihr Code in einer Schleife endet, würde ich empfehlen, null zurückzugeben und darauf zu testen.
quelle
Vergib mir meinen Pseudo-PHP / Code.
Ich denke, es hängt wirklich von der beabsichtigten Verwendung des Ergebnisses ab.
Wenn Sie den Rückgabewert bearbeiten / ändern und speichern möchten, geben Sie ein leeres Objekt zurück. Auf diese Weise können Sie dieselbe Funktion verwenden, um Daten in ein neues oder vorhandenes Objekt einzufügen.
Angenommen, ich habe eine Funktion, die einen Primärschlüssel und ein Datenarray verwendet, die Zeile mit Daten füllt und dann den resultierenden Datensatz in der Datenbank speichert. Da ich beabsichtige, das Objekt so oder so mit meinen Daten zu füllen, kann es ein großer Vorteil sein, ein leeres Objekt vom Getter zurückzubekommen. Auf diese Weise kann ich in beiden Fällen identische Operationen ausführen. Sie verwenden das Ergebnis der Getter-Funktion, egal was passiert.
Beispiel:
Hier können wir sehen, dass dieselbe Reihe von Operationen alle Datensätze dieses Typs manipuliert.
Wenn die endgültige Absicht des Rückgabewerts jedoch darin besteht, etwas mit den Daten zu lesen und zu tun, würde ich null zurückgeben. Auf diese Weise kann ich sehr schnell feststellen, ob keine Daten zurückgegeben wurden, und dem Benutzer die entsprechende Nachricht anzeigen.
Normalerweise fange ich Ausnahmen in meiner Funktion ab, die die Daten abrufen (damit ich Fehlermeldungen usw. protokollieren kann) und gebe dann direkt vom Fang null zurück. Für den Endbenutzer spielt es im Allgemeinen keine Rolle, wo das Problem liegt. Daher finde ich es am besten, meine Fehlerprotokollierung / -verarbeitung direkt in der Funktion zu kapseln, die die Daten abruft. Wenn Sie in einem großen Unternehmen eine gemeinsam genutzte Codebasis verwalten, ist dies besonders vorteilhaft, da Sie selbst dem faulsten Programmierer die ordnungsgemäße Fehlerprotokollierung / -behandlung aufzwingen können.
Beispiel:
Das ist meine allgemeine Regel. Bisher hat es gut funktioniert.
quelle
Interessante Frage und ich denke, es gibt keine "richtige" Antwort, da es immer von der Verantwortung Ihres Codes abhängt. Weiß Ihre Methode, ob keine gefundenen Daten ein Problem darstellen oder nicht? In den meisten Fällen lautet die Antwort "Nein". Deshalb ist es perfekt, Null zurückzugeben und den Anrufer die Situation bearbeiten zu lassen.
Vielleicht besteht ein guter Ansatz zur Unterscheidung von Wurfmethoden von Null-Rückgabemethoden darin, eine Konvention in Ihrem Team zu finden: Methoden, die besagen, dass sie etwas "bekommen", sollten eine Ausnahme auslösen, wenn nichts zu bekommen ist. Methoden, die möglicherweise null zurückgeben, können anders benannt werden, möglicherweise stattdessen "Suchen ...".
quelle
Wenn das zurückgegebene Objekt wiederholt werden kann, würde ich ein leeres Objekt zurückgeben, damit ich nicht zuerst auf null testen muss.
Beispiel:
quelle
Ich möchte von keiner Methode null zurückgeben, sondern stattdessen den Funktionstyp Option verwenden. Methoden, die kein Ergebnis zurückgeben können, geben eine leere Option anstelle von null zurück.
Solche Methoden, die kein Ergebnis zurückgeben können, sollten dies auch durch ihren Namen anzeigen. Normalerweise setze ich Try oder TryGet oder TryFind an den Anfang des Methodennamens, um anzuzeigen, dass möglicherweise ein leeres Ergebnis zurückgegeben wird (z. B. TryFindCustomer, TryLoadFile usw.).
Das lässt den Anrufer verschiedene Techniken anwenden, wie Sammlung Pipelining (siehe Martin Fowler Sammlung Pipeline ) auf das Ergebnis.
Hier ist ein weiteres Beispiel, in dem die Rückgabe von Option anstelle von Null verwendet wird, um die Codekomplexität zu verringern: Reduzieren der zyklomatischen Komplexität: Funktionstyp der Option
quelle
Mehr Fleisch zum Mahlen: Nehmen wir an, mein DAL gibt eine NULL für GetPersonByID zurück, wie von einigen empfohlen. Was soll meine (ziemlich dünne) BLL tun, wenn sie eine NULL erhält? Geben Sie NULL weiter und lassen Sie den Endverbraucher sich darum kümmern (in diesem Fall eine ASP.Net-Seite)? Wie wäre es, wenn die BLL eine Ausnahme auslöst?
Die BLL wird möglicherweise von ASP.Net und Win App oder einer anderen Klassenbibliothek verwendet. Ich denke, es ist unfair zu erwarten, dass der Endverbraucher von sich aus "weiß", dass die Methode GetPersonByID eine Null zurückgibt (es sei denn, es werden Nulltypen verwendet, denke ich ).
Mein Ansatz (für das, was es wert ist) ist, dass mein DAL NULL zurückgibt, wenn nichts gefunden wird. FÜR EINIGE OBJEKTE ist das in Ordnung - es könnte eine 0: viele Liste von Dingen sein, also ist es in Ordnung, keine Dinge zu haben (z. B. eine Liste von Lieblingsbüchern). In diesem Fall gibt meine BLL eine leere Liste zurück. Wenn ich für die meisten Dinge einer einzelnen Entität (z. B. Benutzer, Konto, Rechnung) keine habe, ist dies definitiv ein Problem und eine kostspielige Ausnahme. Da das Abrufen eines Benutzers durch eine eindeutige Kennung, die zuvor von der Anwendung angegeben wurde, immer einen Benutzer zurückgeben sollte, ist die Ausnahme eine "richtige" Ausnahme, wie in ihrer Ausnahme. Der Endverbraucher der BLL (ASP.Net, f'rinstance) erwartet immer nur, dass die Dinge gut laufen, sodass ein nicht behandelter Ausnahmebehandler verwendet wird, anstatt jeden einzelnen Aufruf von GetPersonByID in einen try-catch-Block zu packen.
Wenn mein Ansatz ein eklatantes Problem aufweist, lassen Sie es mich bitte wissen, da ich immer lernbegierig bin. Wie andere Plakate bereits sagten, sind Ausnahmen kostspielige Dinge, und der Ansatz "Zuerst prüfen" ist gut, aber Ausnahmen sollten genau das sein - außergewöhnlich.
Ich genieße diesen Beitrag, viele gute Vorschläge für "es kommt darauf an" -Szenarien :-)
quelle
Ich denke, Funktionen sollten für den Zustand Ihrer Codebasis nicht null zurückgeben. Ich kann mir einige Gründe vorstellen:
Es wird eine große Anzahl von Schutzklauseln geben, die Nullreferenzen behandeln
if (f() != null)
.Was ist
null
, ist es eine akzeptierte Antwort oder ein Problem? Ist null ein gültiger Status für ein bestimmtes Objekt? (Stellen Sie sich vor, Sie sind ein Client für den Code). Ich meine, alle Referenztypen können null sein, aber sollten sie?Haben
null
herumhängen, werden von Zeit zu Zeit fast immer einige unerwartete NullRef-Ausnahmen auftreten, wenn Ihre Codebasis wächst.Es gibt einige Lösungen
tester-doer pattern
oder die Implementierung deroption type
funktionalen Programmierung.quelle
Ich bin ratlos über die Anzahl der Antworten (im gesamten Web), die besagen, dass Sie zwei Methoden benötigen: eine "IsItThere ()" - Methode und eine "GetItForMe ()" - Methode, was zu einer Racebedingung führt. Was ist falsch an einer Funktion, die null zurückgibt, einer Variablen zuweist und die Variable in einem Test auf Null überprüft? Mein früherer C-Code war gespickt mit
if (NULL! = (Variable = Funktion (Argumente ...))) {
Sie erhalten also den Wert (oder Null) in einer Variablen und das Ergebnis auf einmal. Wurde diese Redewendung vergessen? Warum?
quelle
Ich stimme den meisten Posts hier zu, die dazu neigen
null
.Meine Argumentation ist, dass das Generieren eines leeren Objekts mit nicht nullbaren Eigenschaften Fehler verursachen kann. Beispielsweise hätte eine Entität mit einer
int ID
Eigenschaft einen Anfangswert vonID = 0
, was ein vollständig gültiger Wert ist. Sollte dieses Objekt unter bestimmten Umständen in einer Datenbank gespeichert werden, wäre dies eine schlechte Sache.Für alles mit einem Iterator würde ich immer die leere Sammlung verwenden. Etwas wie
ist meiner Meinung nach Codegeruch. Sammlungseigenschaften sollten niemals null sein.
Ein Randfall ist
String
. Viele Leute sagen,String.IsNullOrEmpty
ist nicht wirklich notwendig, aber man kann nicht immer zwischen einer leeren Zeichenfolge und null unterscheiden. Darüber hinaus unterscheiden einige Datenbanksysteme (Oracle) überhaupt nicht zwischen ihnen (''
werden als gespeichertDBNULL
), sodass Sie gezwungen sind, sie gleich zu behandeln. Der Grund dafür ist, dass die meisten Zeichenfolgenwerte entweder von Benutzereingaben oder von externen Systemen stammen, während weder Textfelder noch die meisten Austauschformate unterschiedliche Darstellungen für''
und habennull
. Selbst wenn der Benutzer einen Wert entfernen möchte, kann er nur die Eingabesteuerung löschen. Auch die Unterscheidung von nullbar und nicht nullbarnvarchar
Datenbankfeldern ist mehr als fraglich, wenn Ihr DBMS kein Orakel ist - ein Pflichtfeld, das dies zulässt''
ist seltsam, Ihre Benutzeroberfläche würde dies niemals zulassen, sodass Ihre Einschränkungen nicht zugeordnet werden. Die Antwort hier lautet meiner Meinung nach, immer gleich damit umzugehen.Zu Ihrer Frage zu Ausnahmen und Leistung: Wenn Sie eine Ausnahme auslösen, die Sie in Ihrer Programmlogik nicht vollständig behandeln können, müssen Sie irgendwann abbrechen, was auch immer Ihr Programm tut, und den Benutzer bitten, alles zu wiederholen, was er gerade getan hat. In diesem Fall ist die Leistungseinbuße von a
catch
wirklich die geringste Ihrer Sorgen - wenn Sie den Benutzer fragen müssen, ist dies der Elefant im Raum (was bedeutet, dass die gesamte Benutzeroberfläche neu gerendert oder HTML über das Internet gesendet wird). Wenn Sie also nicht dem Anti-Muster von " Programmablauf mit Ausnahmen " folgen, stören Sie sich nicht, werfen Sie einfach einen, wenn es Sinn macht. Selbst in Grenzfällen wie "Validierungsausnahme" ist die Leistung kein Problem, da Sie den Benutzer auf jeden Fall erneut fragen müssen.quelle
Ein asynchrones TryGet-Muster:
Für synchrone Methoden, glaube ich @Johann Gerell die Antwort ist das Muster in allen Fällen zu verwenden.
Das TryGet-Muster mit dem
out
Parameter funktioniert jedoch nicht mit Async-Methoden.Mit den Tupel-Literalen von C # 7 können Sie jetzt Folgendes tun:
quelle