Meines Erachtens sollten Sie den Wert zurückgeben, der im Kontext semantisch korrekt ist, was auch immer das sein mag. Eine Regel, die besagt, dass man immer eine leere Sammlung zurückgeben sollte, erscheint mir etwas zu simpel.
Nehmen wir an, dass wir in einem System für ein Krankenhaus eine Funktion haben, die eine Liste aller früheren Krankenhausaufenthalte der letzten 5 Jahre zurückgeben soll. Wenn der Kunde noch nicht im Krankenhaus war, ist es sinnvoll, eine leere Liste zurückzugeben. Was aber, wenn der Kunde diesen Teil des Einweisungsformulars 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 das ist nicht notwendigerweise eine Fehlerbedingung, und es bringt uns nicht unbedingt aus dem normalen Programmfluss heraus.
Ich war schon oft von Systemen frustriert, die nicht zwischen Null und keiner Antwort unterscheiden können. Ich habe schon einige Male erlebt, dass ein System mich aufgefordert hat, eine Zahl einzugeben, ich gebe eine Null ein und erhalte eine Fehlermeldung, dass ich einen Wert in dieses Feld eingeben muss. Das habe ich gerade getan: Ich habe Null eingegeben! Aber das System akzeptiert die Null nicht, weil es sie 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 Sinn des letzten Absatzes meiner Antwort. Viele Programme sind nicht in der Lage, "weiß nicht" von "leer" oder "Null" zu unterscheiden, was mir ein potenziell schwerwiegender Fehler zu sein scheint. Ich habe zum Beispiel vor etwa einem Jahr ein Haus gekauft. Ich besuchte eine Immobilien-Website, und dort waren viele Häuser mit einer Preisvorstellung von 0 $ aufgelistet, was sich für mich ziemlich gut anhörte: Sie geben diese Häuser umsonst weg! Aber ich bin sicher, die traurige Wahrheit war, dass sie den Preis einfach nicht eingegeben hatten. In diesem Fall werden Sie vielleicht sagen: "Nun, offensichtlich bedeutet Null, dass sie den Preis nicht eingegeben haben - niemand wird ein Haus umsonst verschenken." Auf der Website wurden jedoch auch die durchschnittlichen Kauf- und Verkaufspreise für Häuser in verschiedenen Städten angegeben. Ich kann nicht umhin, mich zu fragen, ob der Durchschnitt die Nullen nicht mit einschließt, so dass sich für einige Orte ein falsch niedriger Durchschnitt ergibt. z. B. was ist der Durchschnitt von 100.000 $, 120.000 $ und "weiß nicht"? Technisch gesehen lautet die Antwort "weiß nicht". Was wir wahrscheinlich wirklich sehen wollen, ist $110.000. Was wir aber wahrscheinlich erhalten werden, ist 73.333 $, was völlig falsch wäre. Und was wäre, wenn wir dieses Problem auf einer Website hätten, auf der die Benutzer online bestellen können? (Unwahrscheinlich bei Immobilien, aber ich bin sicher, Sie haben das schon bei vielen anderen Produkten gesehen.) Würden wir wirklich wollen, dass "Preis noch nicht festgelegt" als "kostenlos" interpretiert wird?
RE mit zwei getrennten Funktionen, einer "Gibt es eine?" und einer "Wenn ja, welche?" Ja, das könnte man natürlich machen, aber warum sollte man das wollen? Jetzt muss das aufrufende Programm zwei Aufrufe machen, statt einem. Was passiert, wenn ein Programmierer das "any?" nicht aufruft und direkt zum "what is it?" übergeht? ? Gibt das Programm eine irreführende Null zurück? Eine Ausnahme auslösen? Einen undefinierten Wert zurückgeben? Das erzeugt mehr Code, mehr Arbeit und mehr potenzielle Fehler.
Der einzige Vorteil, den ich darin sehe, ist, dass Sie damit eine willkürliche Vorschrift einhalten können. Hat diese Vorschrift irgendeinen Vorteil, der es wert macht, dass man sie befolgt? Wenn nicht, warum sich die Mühe machen?
Antwort an Jammycakes:
Überlegen Sie, wie der eigentliche Code aussehen würde. Ich weiß, in der Frage stand C#, aber entschuldigen Sie, wenn ich Java schreibe. Mein C# ist nicht sehr scharf und das Prinzip ist das gleiche.
Mit einer Null-Rückgabe:
HospList list=patient.getHospitalizationList(patientId);
if (list==null)
{
// ... handle missing list ...
}
else
{
for (HospEntry entry : list)
// ... do whatever ...
}
Mit einer separaten Funktion:
if (patient.hasHospitalizationList(patientId))
{
// ... handle missing list ...
}
else
{
HospList=patient.getHospitalizationList(patientId))
for (HospEntry entry : list)
// ... do whatever ...
}
Mit der Null-Rückgabe sind es sogar ein oder zwei Zeilen weniger Code, so dass der Aufrufer nicht mehr, sondern weniger belastet wird.
Ich sehe nicht, wie dadurch ein DRY-Problem entsteht. Es ist ja nicht so, dass wir den Aufruf zweimal ausführen müssen. Wenn wir immer das Gleiche tun wollten, wenn die Liste nicht existiert, könnten wir vielleicht die Behandlung in die Funktion get-list verlagern, anstatt sie dem Aufrufer zu überlassen, so dass es eine DRY-Verletzung wäre, den Code in den Aufrufer zu stellen. Aber wir wollen mit Sicherheit nicht immer das Gleiche tun. In Funktionen, bei denen wir die Liste zur Verarbeitung benötigen, ist eine fehlende Liste ein Fehler, der die Verarbeitung unterbrechen könnte. Aber auf einer Eingabemaske wollen wir die Verarbeitung sicher nicht unterbrechen, wenn der Benutzer noch keine Daten eingegeben hat: Wir wollen ihn Daten eingeben lassen. Die Behandlung von "keine Liste" muss also auf die eine oder andere Weise auf der Ebene des Anrufers erfolgen. Und ob wir das mit einer Null-Rückgabe oder einer separaten Funktion tun, macht keinen Unterschied für das übergeordnete Prinzip.
Klar, wenn der Aufrufer nicht auf Null prüft, kann das Programm mit einer Null-Zeiger-Ausnahme fehlschlagen. Aber wenn es eine separate "got any"-Funktion gibt und der Aufrufer diese Funktion nicht aufruft, sondern blindlings die "get list"-Funktion aufruft, was passiert dann? Wenn sie eine Ausnahme auslöst oder anderweitig fehlschlägt, ist das so ziemlich das Gleiche, was passieren würde, wenn sie null zurückgibt und nicht darauf prüft. Wenn sie eine leere Liste zurückgibt, ist das einfach falsch. Du unterscheidest nicht zwischen "Ich habe eine Liste mit null Elementen" und "Ich habe keine Liste". Das ist so, als würde man für den Preis null zurückgeben, wenn der Benutzer keinen Preis eingegeben hat: Das ist einfach falsch.
Ich verstehe nicht, wie das Anhängen eines zusätzlichen Attributs an die Sammlung helfen soll. Der Aufrufer muss es immer noch überprüfen. Inwiefern ist das besser als die Prüfung auf Null? Nochmals: Das Schlimmste, was passieren kann, ist, dass der Programmierer vergisst, es zu prü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, und ich denke, dass jeder kompetente Programmierer davon gehört haben sollte, ob er es für eine gute Idee hält oder nicht. Ich denke, eine separate Funktion ist eher ein "Überraschungsproblem". Wenn ein Programmierer mit der API nicht vertraut ist, wird er, wenn er einen Test ohne Daten durchführt, schnell feststellen, dass er manchmal eine Null zurückbekommt. Aber wie würde er die Existenz einer anderen Funktion entdecken, wenn er nicht auf die Idee käme, dass es eine solche Funktion geben könnte, und wenn er in der Dokumentation nachschaut, und die Dokumentation ist vollständig und verständlich? Ich hätte viel lieber eine Funktion, die mir immer eine sinnvolle Antwort gibt, als zwei Funktionen, die ich kennen und mir merken muss, um beide aufzurufen.
0 Stimmen
Dies ist eine subjektive Frage, bei der es auf beiden Seiten leidenschaftliche Gläubige gibt. Es gibt keine allgemein anerkannte "beste Praxis".
5 Stimmen
Ähm, nicht ganz CPerkins. rads.stackoverflow.com/amzn/click/0321545613
1 Stimmen
Nun, es gibt eine bewährte Praxis, von der es aber auch begründete Ausnahmen gibt.
3 Stimmen
@CPerkins - Ja, die gibt es. Es ist klar in Microsofts eigenen .NET-Framework-Entwurfsrichtlinien festgelegt. Siehe RichardOD's Antwort für die Details.
0 Stimmen
Die Sprache, um die es hier geht, ist zwar C#, aber alle diese Leitlinien gelten für jede objektorientierte Sprache, die es gibt.
55 Stimmen
NUR wenn die Bedeutung "Ich kann die Ergebnisse nicht berechnen" ist, sollten Sie null zurückgeben. Null sollte nie die Semantik von "leer" haben, sondern nur "fehlend" oder "unbekannt". Weitere Einzelheiten finden Sie in meinem Artikel zu diesem Thema: blogs.msdn.com/ericlippert/archive/2009/05/14/
3 Stimmen
Bozho: "Jede" ist eine ganze Menge von Sprachen. Wie wäre es mit Common Lisp, wo die leere Liste genau gleich dem Nullwert ist :-)
1 Stimmen
Duplikat: stackoverflow.com/questions/1626597/
9 Stimmen
Eigentlich geht es bei dem "Duplikat" um Methoden, die ein Objekt zurückgeben, nicht um eine Sammlung. Es ist ein anderes Szenario mit anderen Antworten.
0 Stimmen
@EricLippert der Link scheint jetzt auf eine Blog-Verzeichnis-Seite umzuleiten. Kannst du den Link aktualisieren? Danke!
0 Stimmen
@TheMuffinMan: Sie können alte Kommentare leider nicht bearbeiten. Microsoft verschiebt ständig den Ort, an dem sich mein alter Blog befindet. Der neue Link ist learn.microsoft.com/de-us/archive/blogs/ericlippert/
0 Stimmen
Ich hatte diese Frage auch, aber ich denke, null ist nicht leer Sammlung und es kann Problem in einigen Codes verursachen.