Das ist eine Art allgemeine Frage (aber ich verwende C #). Was ist der beste Weg (Best Practice)? Geben Sie für eine Methode, die eine Sammlung als Rückgabetyp hat, null oder leere Sammlung zurück?
c#
collections
Omu
quelle
quelle
Antworten:
Leere Sammlung. Immer.
Das ist scheiße:
Es wird als bewährte Methode angesehen, NIEMALS zurückzukehren,
null
wenn eine Sammlung oder eine Aufzählung zurückgegeben wird. Geben Sie IMMER eine leere Aufzählung / Sammlung zurück. Es verhindert den oben genannten Unsinn und verhindert, dass Ihr Auto von Mitarbeitern und Benutzern Ihrer Klassen angeregt wird.Wenn Sie über Eigenschaften sprechen, stellen Sie Ihre Eigenschaft immer einmal ein und vergessen Sie sie
In .NET 4.6.1 können Sie dies ziemlich stark komprimieren:
Wenn Sie über Methoden sprechen, die Enumerables zurückgeben, können Sie einfach eine leere Enumerable anstelle von
null
... zurückgeben.Die Verwendung
Enumerable.Empty<T>()
kann als effizienter angesehen werden, als beispielsweise eine neue leere Sammlung oder ein neues Array zurückzugeben.quelle
IEnumerable
oderICollection
nicht. Wie auch immer, wenn Sie etwas vom Typ auswählen, gebenICollection
sie auch zurücknull
... Ich möchte, dass sie eine leere Sammlung zurückgeben, aber ich bin auf sie gestoßennull
, also dachte ich, ich würde es hier nur erwähnen. Ich würde sagen, der Standardwert einer Sammlung von Aufzählungszeichen ist leer und nicht null. Ich wusste nicht, dass es ein so sensibles Thema ist.Aus den Framework Design Guidelines 2nd Edition (S. 256):
Hier ist ein weiterer interessanter Artikel über die Vorteile der Nichtrückgabe von Nullen (ich habe versucht, etwas in Brad Abrams Blog zu finden, und er hat auf den Artikel verlinkt).
Bearbeiten - wie Eric Lippert jetzt die ursprüngliche Frage kommentiert hat, möchte ich auch auf seinen ausgezeichneten Artikel verlinken .
quelle
Hängt von Ihrem Vertrag und Ihrem konkreten Fall ab . Im Allgemeinen ist es am besten, leere Sammlungen zurückzugeben , aber manchmal ( selten) ):
null
könnte etwas Spezifischeres bedeuten;null
.Einige konkrete Beispiele:
null
würde bedeuten, dass das Element fehlt, während eine leere Sammlung ein redundantes (und möglicherweise falsches) Element rendern würde.<collection />
quelle
Es gibt noch einen weiteren Punkt, der noch nicht erwähnt wurde. Betrachten Sie den folgenden Code:
Die C # -Sprache gibt beim Aufrufen dieser Methode einen leeren Enumerator zurück. Um mit dem Sprachdesign (und damit den Erwartungen des Programmierers) übereinzustimmen, sollte daher eine leere Sammlung zurückgegeben werden.
quelle
Leer ist viel verbraucherfreundlicher.
Es gibt eine klare Methode, um eine leere Aufzählung zu erstellen:
quelle
Es scheint mir, dass Sie den Wert zurückgeben sollten, der im Kontext semantisch korrekt ist, was auch immer das sein mag. Eine Regel mit der Aufschrift "Immer eine leere Sammlung zurückgeben" erscheint mir etwas simpel.
Angenommen, wir haben beispielsweise in einem System für ein Krankenhaus eine Funktion, die eine Liste aller früheren Krankenhausaufenthalte der letzten 5 Jahre zurückgeben soll. Wenn der Kunde nicht im Krankenhaus war, ist es sinnvoll, eine leere Liste zurückzugeben. Was aber, wenn der Kunde diesen Teil des Zulassungsformulars leer gelassen hat? Wir brauchen einen anderen Wert, um "leere Liste" von "keine Antwort" oder "weiß nicht" zu unterscheiden. Wir könnten eine Ausnahme auslösen, aber dies ist nicht unbedingt eine Fehlerbedingung und führt uns nicht unbedingt aus dem normalen Programmablauf heraus.
Ich war oft frustriert von Systemen, die nicht zwischen Null und Keine Antwort unterscheiden können. Ich wurde mehrmals von einem System aufgefordert, eine Zahl einzugeben. Ich gebe Null ein und erhalte die Fehlermeldung, dass ich einen Wert in dieses Feld eingeben muss. Ich habe es gerade getan: Ich habe Null eingegeben! Aber es akzeptiert keine Null, weil es es nicht von keiner Antwort unterscheiden kann.
Antwort an Saunders:
Ja, ich gehe davon aus, dass es einen Unterschied zwischen "Person hat die Frage nicht beantwortet" und "Die Antwort war Null" gibt. Das war der Punkt des letzten Absatzes meiner Antwort. Viele Programme sind nicht in der Lage, "Weiß nicht" von Leer oder Null zu unterscheiden, was mir als potenziell schwerwiegender Fehler erscheint. Zum Beispiel habe ich vor ungefähr einem Jahr ein Haus gekauft. Ich ging zu einer Immobilien-Website und es gab viele Häuser mit einem Preis von 0 US-Dollar. Hört sich für mich ziemlich gut an: Sie verschenken diese Häuser kostenlos! Aber ich bin sicher, die traurige Realität war, dass sie den Preis einfach nicht eingegeben hatten. In diesem Fall können Sie sagen: "Nun, offensichtlich Null bedeutet, dass sie den Preis nicht eingegeben haben - niemand wird ein Haus kostenlos verschenken." Die Website listete aber auch die durchschnittlichen Angebots- und Verkaufspreise von Häusern in verschiedenen Städten auf. Ich kann nicht anders, als mich zu fragen, ob der Durchschnitt die Nullen nicht enthielt, was für einige Orte einen falsch niedrigen Durchschnitt ergibt. dh was ist der Durchschnitt von 100.000 $; 120.000 US-Dollar; und "weiß nicht"? Technisch lautet die Antwort "Weiß nicht". Was wir wahrscheinlich wirklich sehen wollen, sind 110.000 US-Dollar. Aber was wir wahrscheinlich bekommen werden, sind 73.333 Dollar, was völlig falsch wäre. Was wäre, wenn wir dieses Problem auf einer Website hätten, auf der Benutzer online bestellen können? (Unwahrscheinlich für Immobilien, aber ich bin sicher, dass Sie dies bei vielen anderen Produkten gesehen haben.) Würden wir wirklich wollen, dass "Preis noch nicht angegeben" als "kostenlos" interpretiert wird? Dies ergibt für einige Orte einen falsch niedrigen Durchschnitt. dh was ist der Durchschnitt von 100.000 $; 120.000 US-Dollar; und "weiß nicht"? Technisch lautet die Antwort "Weiß nicht". Was wir wahrscheinlich wirklich sehen wollen, sind 110.000 US-Dollar. Aber was wir wahrscheinlich bekommen werden, sind 73.333 Dollar, was völlig falsch wäre. Was wäre, wenn wir dieses Problem auf einer Website hätten, auf der Benutzer online bestellen können? (Unwahrscheinlich für Immobilien, aber ich bin sicher, dass Sie dies bei vielen anderen Produkten gesehen haben.) Würden wir wirklich wollen, dass "Preis noch nicht angegeben" als "kostenlos" interpretiert wird? Dies ergibt für einige Orte einen falsch niedrigen Durchschnitt. dh was ist der Durchschnitt von 100.000 $; 120.000 US-Dollar; und "weiß nicht"? Technisch lautet die Antwort "Weiß nicht". Was wir wahrscheinlich wirklich sehen wollen, sind 110.000 US-Dollar. Aber was wir wahrscheinlich bekommen werden, sind 73.333 Dollar, was völlig falsch wäre. Was wäre, wenn wir dieses Problem auf einer Website hätten, auf der Benutzer online bestellen können? (Unwahrscheinlich für Immobilien, aber ich bin sicher, dass Sie dies bei vielen anderen Produkten gesehen haben.) Würden wir wirklich wollen, dass "Preis noch nicht angegeben" als "kostenlos" interpretiert wird? das wäre völlig falsch. Was wäre, wenn wir dieses Problem auf einer Website hätten, auf der Benutzer online bestellen können? (Unwahrscheinlich für Immobilien, aber ich bin sicher, dass Sie dies bei vielen anderen Produkten gesehen haben.) Würden wir wirklich wollen, dass "Preis noch nicht angegeben" als "kostenlos" interpretiert wird? das wäre völlig falsch. Was wäre, wenn wir dieses Problem auf einer Website hätten, auf der Benutzer online bestellen können? (Unwahrscheinlich für Immobilien, aber ich bin sicher, dass Sie dies bei vielen anderen Produkten gesehen haben.) Würden wir wirklich wollen, dass "Preis noch nicht angegeben" als "kostenlos" interpretiert wird?
RE hat zwei separate Funktionen, ein "Gibt es welche?" und ein "wenn ja, was ist es?" Ja, das könnten Sie sicherlich tun, aber warum sollten Sie das wollen? Jetzt muss das aufrufende Programm zwei Aufrufe anstelle von einem tätigen. Was passiert, wenn ein Programmierer das "any" nicht aufruft? und geht direkt zum "Was ist das?" ? Gibt das Programm eine falsch führende Null zurück? Eine Ausnahme werfen? Einen undefinierten Wert zurückgeben? Es schafft mehr Code, mehr Arbeit und mehr potenzielle Fehler.
Der einzige Vorteil, den ich sehe, ist, dass Sie eine beliebige Regel einhalten können. Gibt es einen Vorteil dieser Regel, der es sich lohnt, sie einzuhalten? Wenn nicht, warum dann?
Antwort auf Jammycakes:
Überlegen Sie, wie der eigentliche Code aussehen würde. Ich weiß, dass die Frage C # lautete, aber entschuldigen Sie, wenn ich Java schreibe. Mein C # ist nicht sehr scharf und das Prinzip ist das gleiche.
Mit einer Null-Rückgabe:
Mit einer separaten Funktion:
Es ist tatsächlich ein oder zwei Zeilen weniger Code mit der Null-Rückgabe, sodass der Anrufer nicht mehr belastet wird, sondern weniger.
Ich sehe nicht, wie es ein trockenes Problem schafft. Es ist nicht so, dass wir den Anruf zweimal ausführen müssen. Wenn wir immer das Gleiche tun wollten, wenn die Liste nicht vorhanden ist, könnten wir die Behandlung möglicherweise auf die Funktion "Get-List" beschränken, anstatt den Anrufer dies tun zu lassen. Daher wäre das Einfügen des Codes in den Anrufer eine DRY-Verletzung. Aber wir wollen mit ziemlicher Sicherheit nicht immer das Gleiche tun. In Funktionen, in denen die Liste verarbeitet werden muss, ist eine fehlende Liste ein Fehler, der die Verarbeitung möglicherweise anhält. Aber auf einem Bearbeitungsbildschirm möchten wir die Verarbeitung sicherlich nicht anhalten, wenn sie noch keine Daten eingegeben haben. Wir möchten, dass sie Daten eingeben. Die Behandlung von "keine Liste" muss also auf die Anrufer-Ebene auf die eine oder andere Weise erfolgen. Und ob wir das mit einer Null-Rückgabe oder einer separaten Funktion machen, spielt für das größere Prinzip keine Rolle.
Sicher, wenn der Aufrufer nicht nach null sucht, kann das Programm mit einer Nullzeigerausnahme fehlschlagen. Aber wenn es eine separate "got any" -Funktion gibt und der Aufrufer diese Funktion nicht aufruft, sondern blind die "get list" -Funktion aufruft, was passiert dann? Wenn es eine Ausnahme auslöst oder auf andere Weise fehlschlägt, ist das so ziemlich das Gleiche wie das, was passieren würde, wenn es null zurückgibt und nicht danach sucht. Wenn eine leere Liste zurückgegeben wird, ist das einfach falsch. Sie können nicht zwischen "Ich habe eine Liste mit null Elementen" und "Ich habe keine Liste" unterscheiden. Es ist, als würde man für den Preis Null zurückgeben, wenn der Benutzer keinen Preis eingegeben hat: Es ist einfach falsch.
Ich sehe nicht, wie das Anhängen eines zusätzlichen Attributs an die Sammlung hilft. Der Anrufer muss es noch überprüfen. Wie ist das besser als nach Null zu suchen? Das absolut Schlimmste, was passieren kann, ist, dass der Programmierer vergisst, es zu überprüfen, und falsche Ergebnisse liefert.
Eine Funktion, die null zurückgibt, ist keine Überraschung, wenn der Programmierer mit dem Konzept von null vertraut ist, das "keinen Wert haben" bedeutet. Ich denke, jeder kompetente Programmierer hätte davon hören sollen, ob er es für eine gute Idee hält oder nicht. Ich denke, eine separate Funktion zu haben, ist eher ein "Überraschungs" -Problem. Wenn ein Programmierer mit der API nicht vertraut ist und einen Test ohne Daten ausführt, stellt er schnell fest, dass er manchmal eine Null zurückerhält. Aber wie würde er die Existenz einer anderen Funktion entdecken, wenn ihm nicht in den Sinn käme, dass es eine solche Funktion geben könnte, und er die Dokumentation überprüft und die Dokumentation vollständig und verständlich ist? Ich hätte viel lieber eine Funktion, die mir immer eine aussagekräftige Antwort gibt, als zwei Funktionen, die ich kennen und daran denken muss, beide aufzurufen.
quelle
Wenn eine leere Sammlung semantisch Sinn macht, kehre ich lieber zurück. Rückgabe einer leeren Sammlung für
GetMessagesInMyInbox()
Mitteilungen "Sie haben wirklich keine Nachrichten in Ihrem Posteingang", während die Rückgabenull
hilfreich sein kann, um mitzuteilen, dass nicht genügend Daten verfügbar sind, um zu sagen, wie die möglicherweise zurückgegebene Liste aussehen soll.quelle
null
Wert sicherlich nicht vernünftig. Ich habe allgemeiner darüber nachgedacht. Ausnahmen sind auch großartig, um die Tatsache zu kommunizieren, dass etwas schief gelaufen ist, aber wenn die "unzureichenden Daten", auf die Bezug genommen wird, perfekt erwartet werden, dann würde das Auslösen einer Ausnahme ein schlechtes Design bedeuten. Ich denke eher an ein Szenario, in dem es durchaus möglich und überhaupt kein Fehler ist, dass die Methode manchmal nicht in der Lage ist, eine Antwort zu berechnen.Die Rückgabe von null könnte effizienter sein, da kein neues Objekt erstellt wird. Es würde jedoch häufig auch eine
null
Überprüfung (oder Ausnahmebehandlung) erfordern .Semantisch gesehen
null
und eine leere Liste bedeuten nicht dasselbe. Die Unterschiede sind subtil und eine Wahl kann in bestimmten Fällen besser sein als die andere.Dokumentieren Sie es unabhängig von Ihrer Wahl, um Verwirrung zu vermeiden.
quelle
Man könnte argumentieren, dass die Argumentation hinter Null Object Pattern ähnlich ist wie die für die Rückgabe der leeren Sammlung.
quelle
Es kommt auf die Situation an. Wenn es sich um einen Sonderfall handelt, geben Sie null zurück. Wenn die Funktion zufällig eine leere Sammlung zurückgibt, ist dies offensichtlich in Ordnung. Die Rückgabe einer leeren Sammlung als Sonderfall aufgrund ungültiger Parameter oder aus anderen Gründen ist jedoch KEINE gute Idee, da dadurch eine Sonderfallbedingung maskiert wird.
Eigentlich ziehe ich es in diesem Fall normalerweise vor, eine Ausnahme auszulösen, um sicherzustellen, dass sie WIRKLICH nicht ignoriert wird :)
Zu sagen, dass der Code dadurch robuster wird (indem eine leere Sammlung zurückgegeben wird), da sie die Nullbedingung nicht behandeln müssen, ist schlecht, da lediglich ein Problem maskiert wird, das vom aufrufenden Code behandelt werden sollte.
quelle
Ich würde argumentieren, dass dies
null
nicht dasselbe ist wie eine leere Sammlung, und Sie sollten auswählen, welche am besten für Ihre Rückgabe steht. In den meisten Fällennull
ist nichts (außer in SQL). Eine leere Sammlung ist etwas, wenn auch ein leeres Etwas.Wenn Sie sich für die eine oder andere entscheiden müssen, würde ich sagen, dass Sie eher zu einer leeren Sammlung als zu Null tendieren sollten. Es gibt jedoch Situationen, in denen eine leere Sammlung nicht mit einem Nullwert identisch ist.
quelle
Denken Sie immer zugunsten Ihrer Kunden (die Ihre API verwenden):
Die Rückgabe von 'null' führt sehr häufig zu Problemen mit Clients, die Nullprüfungen nicht korrekt verarbeiten, was zur Laufzeit zu einer NullPointerException führt. Ich habe Fälle gesehen, in denen eine solche fehlende Nullprüfung ein vorrangiges Produktionsproblem erzwang (ein Client, der für jeden (...) einen Nullwert verwendet hat). Während des Tests trat das Problem nicht auf, da die bearbeiteten Daten geringfügig voneinander abweichen.
quelle
Ich möchte hier mit einem geeigneten Beispiel erklären.
Betrachten Sie hier einen Fall.
Hier Betrachten Sie die Funktionen, die ich benutze ..
Ich kann leicht verwenden
ListCustomerAccount
undFindAll
statt.,.HINWEIS: Da AccountValue nicht aktiviert ist
null
, wird die Funktion Sum () nicht zurückgegebennull
. Daher kann ich sie direkt verwenden.quelle
Wir hatten diese Diskussion vor ungefähr einer Woche im Entwicklungsteam bei der Arbeit und haben uns fast einstimmig für eine leere Sammlung entschieden. Eine Person wollte aus demselben Grund, den Mike oben angegeben hatte, null zurückgeben.
quelle
Leere Sammlung. Wenn Sie C # verwenden, wird davon ausgegangen, dass die Maximierung der Systemressourcen nicht unbedingt erforderlich ist. Die Rückgabe der leeren Sammlung ist zwar weniger effizient, für die beteiligten Programmierer jedoch viel bequemer (aus dem oben beschriebenen Grund).
quelle
In den meisten Fällen ist es besser, eine leere Sammlung zurückzugeben.
Der Grund dafür ist die bequeme Implementierung des Anrufers, der konsistente Vertrag und die einfachere Implementierung.
Wenn eine Methode null zurückgibt, um ein leeres Ergebnis anzuzeigen, muss der Aufrufer zusätzlich zur Aufzählung einen Nullprüfadapter implementieren. Dieser Code wird dann in verschiedenen Aufrufern dupliziert. Warum also nicht diesen Adapter in die Methode einfügen, damit er wiederverwendet werden kann?
Eine gültige Verwendung von null für IEnumerable kann ein Hinweis auf ein fehlendes Ergebnis oder einen Operationsfehler sein. In diesem Fall sollten jedoch andere Techniken in Betracht gezogen werden, z. B. das Auslösen einer Ausnahme.
quelle
Sehen Sie hier für eine aufwendige Scheiße Sturm über
null
im Allgemeinen. Ich stimme der Aussage nicht zu, dieundefined
eine andere istnull
, aber es lohnt sich immer noch zu lesen. Und es erklärt, warum Sie überhaupt vermeiden solltennull
und nicht nur für den Fall, dass Sie gefragt haben. Das Wesentliche ist, dassnull
in jeder Sprache ein Sonderfall vorliegt. Sie müssennull
als Ausnahme denken .undefined
unterscheidet sich in dieser Hinsicht, dass Code, der sich mit undefiniertem Verhalten befasst, in den meisten Fällen nur ein Fehler ist. C und die meisten anderen Sprachen haben ebenfalls ein undefiniertes Verhalten, aber die meisten von ihnen haben keine Kennung dafür in der Sprache.quelle
Unter dem Gesichtspunkt des Komplexitätsmanagements, einem primären Ziel des Software-Engineerings, möchten wir eine unnötige Verbreitung vermeiden zyklomatische Komplexität auf die Clients einer API übertragen wird. Das Zurückgeben einer Null an den Client entspricht dem Zurückgeben der zyklomatischen Komplexitätskosten eines anderen Codezweigs.
(Dies entspricht einer Unit-Test-Belastung. Sie müssten zusätzlich zum leeren Collection-Return-Fall einen Test für den Null-Return-Fall schreiben.)
quelle