Standard-String-Initialisierung: NULL oder leer? [geschlossen]


130

Ich habe meine Zeichenfolgen immer mit NULL initialisiert, mit dem Gedanken, dass NULL das Fehlen eines Werts bedeutet und "" oder String.Empty ein gültiger Wert ist. Ich habe in letzter Zeit weitere Beispiele für Code gesehen, bei denen String.Empty als Standardwert betrachtet wird oder keinen Wert darstellt. Das kommt mir seltsam vor. Bei den neu hinzugefügten nullbaren Typen in c # scheinen wir mit Strings rückwärts zu gehen, indem wir nicht NULL verwenden, um 'No Value' darzustellen.

Was verwenden Sie als Standardinitialisierer und warum?

Edit: Basierend auf den Antworten führe ich meine weiteren Gedanken weiter

  1. Fehlerbehandlung vermeiden Wenn der Wert nicht null sein sollte, warum wurde er überhaupt gesetzt NULL? Vielleicht ist es besser, den Fehler an der Stelle zu identifizieren, an der er auftritt, als ihn im Rest Ihrer Codebasis zu vertuschen?

  2. Vermeiden von Nullprüfungen Wenn Sie es satt haben, Nullprüfungen im Code durchzuführen, ist es nicht besser, die Nullprüfungen zu abstrahieren? Vielleicht die String-Methoden umbrechen (oder erweitern!), Um sie NULLsicher zu machen ? Was passiert, wenn Sie ständig verwenden String.Emptyund eine Null in Ihr System NULLeingeht? Fügen Sie trotzdem Schecks hinzu?

Ich kann nicht anders, als zu der Meinung zurückzukehren, dass es Faulheit ist. Jeder DBA würde Sie auf neun Arten dumm machen, wenn Sie '' statt nullin seiner Datenbank verwenden würden. Ich denke, die gleichen Prinzipien gelten für die Programmierung, und es sollte jemanden geben, der diejenigen auf den Kopf schlägt, die verwenden, String.Emptyanstatt NULLkeinen Wert darzustellen.

Verwandte Fragen


"The Sane"? Darf keine Dana sein, die ich kenne.
Vfilby

@ Joel, ich bin erstaunt, wie viele Leute keine Ahnung von Zim oder GIR haben. Ich bin auch erstaunt über einige meiner Freunde, die es abstoßend finden. Nicht zu sagen, dass es reine Güte ist, aber es gibt tolle Nuggets an Humor.
Vfilby

Ich weiß, aber manchmal macht es Spaß, etwas anderes vorzutäuschen.
Dana the Sane

1
Ich bin häufig auf dieses Problem bei MVC-Formularsammlungen oder Sitzungsvariablen gestoßen. Ich fand es am nützlichsten, null in String umzuwandeln. Leer mit dem ?? Kurzform, und wenden Sie dann die erforderliche Zeichenfolgenoperation an. z.B. (item ?? String.Empty) .Trim (). ToUpper ()
sonjz

4
das ist nicht konstruktiv?
Nawfal

Antworten:


111

+1 zur Unterscheidung zwischen "leer" und NULL. Ich bin damit einverstanden, dass "leer" "gültig, aber leer" und "NULL" "ungültig" bedeuten sollte.

Also würde ich Ihre Frage so beantworten:

leer, wenn ich einen gültigen Standardwert möchte, der geändert werden kann oder nicht, z. B. den zweiten Vornamen eines Benutzers.

NULL, wenn es sich um einen Fehler handelt, wenn der folgende Code den Wert nicht explizit festlegt.


11
Die Unterscheidung zwischen NULL und leer ist großartig, wenn es tatsächlich einen Unterschied zwischen den beiden gibt. Es gibt jedoch viele Fälle, in denen es keinen Unterschied gibt und daher zwei Möglichkeiten zur Darstellung derselben Sache eine Haftung darstellen.
Greg Smalter

6
@ Greg: Obwohl ich der Meinung bin, dass Vielfalt das Potenzial für Verwirrung hat, kann sie auch ein großer Vorteil sein. Die einfache, konsistente Konvention, "" oder NULL zu schreiben, um zwischen gültigen und ungültigen Werten zu unterscheiden, erleichtert das Verständnis Ihres Codes. Deshalb teste ich Boolesche Werte immer mit "if (var)", Zeigern mit "if (var! = NULL)" und ganzen Zahlen mit "if (var! = 0)" - sie alle bedeuten für den Compiler dasselbe. Sie enthalten jedoch zusätzliche Informationen, die dem armen Entwickler helfen, der meinen Code verwaltet.
Adam Liss

32

Laut MSDN :

Indem Sie Zeichenfolgen mit dem EmptyWert anstelle von initialisieren null, können Sie die Wahrscheinlichkeit eines NullReferenceExceptionAuftretens verringern .

Immer zu verwenden IsNullOrEmpty()ist dennoch eine gute Praxis.


45
Nur weil Sie die Wahrscheinlichkeit der Ausnahme verringern, bedeutet dies nicht, dass die Ausnahme nicht auftreten sollte. Wenn Ihr Code davon abhängt, dass ein Wert vorhanden ist, sollte er eine Ausnahme auslösen!
rmeador

1
Klar, da gibt es kein Argument. OTOH, wenn Sie nur Zeichenfolgen anhängen ... Ich denke, das hängt vom Codierungsstil, der Erfahrung und der Situation ab.
Tomalak

Dies ist hauptsächlich das, was ich benutze, um zu unterscheiden, was ich auch verwenden soll.
PositiveGuy

3
Vergessen Sie nicht IsNullOrWhiteSpace () für .NET Framework 4+
Coops

13

Warum soll Ihre Zeichenfolge überhaupt initialisiert werden? Sie müssen eine Variable nicht initialisieren, wenn Sie eine deklarieren, und IMO sollten Sie dies nur tun, wenn der von Ihnen zugewiesene Wert im Kontext des Codeblocks gültig ist.

Ich sehe das sehr:

string name = null; // or String.Empty
if (condition)
{
  name = "foo";
}
else
{
  name = "bar";
}

return name;

Nicht auf Null zu initialisieren wäre genauso effektiv. Außerdem möchten Sie meistens, dass ein Wert zugewiesen wird. Wenn Sie auf null initialisieren, können Sie möglicherweise Codepfade übersehen, die keinen Wert zuweisen. Wie so:

string name = null; // or String.Empty
if (condition)
{
  name = "foo";
}
else if (othercondition)
{
  name = "bar";
}

return name; //returns null when condition and othercondition are false

Wenn Sie nicht auf null initialisieren, generiert der Compiler einen Fehler, der besagt, dass nicht alle Codepfade einen Wert zuweisen. Dies ist natürlich ein sehr einfaches Beispiel ...

Matthijs


In Visual Studio, von dem ich glaube, dass fast jeder C # -Programmierer es verwendet, würde Ihre zweite Situation (ohne = null) eine Warnung generieren, genau aus dem von Ihnen angegebenen Grund - es spielt keine Rolle, ob der Standardwert einer Zeichenfolge null ist. Wenn Sie nicht über jeden Codepfad eine Zuweisung garantieren, generiert die IDE (und / oder der zugrunde liegende Compiler [?]) eine Warnung. Obwohl Warnungen die Kompilierung nicht verhindern, sind sie immer noch vorhanden. Wenn Sie Warnungen lassen, die leicht zu lösen sind, können Sie andere verschleiern, die die Aufmerksamkeit des Programmierers rechtfertigen könnten
Code Jockey

meines Wissens wird die erste Situation vollkommen glücklich sein , ohne Initialisierung namezu null(keine Warnung), weil jeder Codepfad einen Wert zuweist name- keine Notwendigkeit , es zu initialisieren , an allen
Code Jockey

8

Bei den meisten Programmen, bei denen es sich nicht um Software zur Verarbeitung von Zeichenfolgen handelt, sollte die Programmlogik nicht vom Inhalt der Zeichenfolgenvariablen abhängen. Wann immer ich so etwas in einem Programm sehe:

if (s == "value")

Ich habe ein schlechtes Gefühl. Warum gibt es in dieser Methode ein String-Literal? Was ist die Einstellung s? Weiß es, dass die Logik vom Wert der Zeichenfolge abhängt? Weiß es, dass es Kleinbuchstaben sein muss, um zu arbeiten? Sollte ich dies beheben, indem ich es auf "Verwendung" String.Compareändere? Sollte ich ein erstellen Enumund darin analysieren?

Aus dieser Perspektive gelangt man zu einer ziemlich einfachen Code-Philosophie: Sie vermeiden es, den Inhalt einer Zeichenfolge zu untersuchen, wo immer dies möglich ist. Das Vergleichen eines Strings mit String.Emptyist wirklich nur ein Sonderfall des Vergleichens mit einem Literal: Es ist etwas, das Sie vermeiden sollten, es sei denn, Sie müssen es wirklich tun.

Wenn ich das weiß, blinke ich nicht, wenn ich so etwas in unserer Codebasis sehe:

string msg = Validate(item);
if (msg != null)
{
   DisplayErrorMessage(msg);
   return;
}

Ich weiß, dass Validatedas niemals zurückkehren würde String.Empty, weil wir besseren Code schreiben.

Natürlich funktioniert der Rest der Welt nicht so. Wenn Ihr Programm Benutzereingaben, Datenbanken, Dateien usw. verarbeitet, müssen Sie andere Philosophien berücksichtigen. Dort ist es die Aufgabe Ihres Codes, dem Chaos Ordnung zu verleihen. Ein Teil dieser Reihenfolge besteht darin, zu wissen, wann eine leere Zeichenfolge bedeuten soll String.Emptyund wann sie bedeuten soll null.

(Nur um sicherzugehen, dass ich nicht aus meinem Arsch geredet habe, habe ich nur unsere Codebasis nach "String.IsNullOrEmpty" durchsucht. Alle 54 Vorkommen befinden sich in Methoden, die Benutzereingaben verarbeiten, Werte aus Python-Skripten zurückgeben und Werte untersuchen, aus denen sie abgerufen wurden externe APIs usw.)


6

Dies ist tatsächlich eine Lücke in der C # -Sprache. Es gibt keine Möglichkeit, eine Zeichenfolge zu definieren, die nicht null sein darf. Dies führt zu so einfachen Problemen wie dem von Ihnen beschriebenen, wodurch Programmierer gezwungen werden, eine Entscheidung zu treffen, die sie nicht treffen sollten, da in vielen Fällen NULL und String.Empty dasselbe bedeuten. Dies kann später dazu führen, dass andere Programmierer sowohl NULL als auch String.Empty verarbeiten müssen, was ärgerlich ist.

Ein größeres Problem besteht darin, dass Sie in Datenbanken Felder definieren können, die einer C # -String zugeordnet sind. Datenbankfelder können jedoch als NICHT NULL definiert werden. Es gibt also keine Möglichkeit, beispielsweise ein varchar (100) NOT NULL-Feld in SQL Server mithilfe eines C # -Typs genau darzustellen.

Andere Sprachen, wie z. B. Spec #, erlauben dies.

Meiner Meinung nach ist die Unfähigkeit von C #, eine Zeichenfolge zu definieren, die keine Null zulässt, genauso schlecht wie die vorherige Unfähigkeit, eine Int zu definieren, die Null zulässt.

Um Ihre Frage vollständig zu beantworten: Ich verwende immer eine leere Zeichenfolge für die Standardinitialisierung, da diese der Funktionsweise von Datenbankdatentypen ähnlicher ist. (Bearbeiten: Diese Anweisung war sehr unklar. Sie sollte lauten: "Ich verwende eine leere Zeichenfolge für die Standardinitialisierung, wenn NULL ein überflüssiger Status ist, ähnlich wie ich eine Datenbankspalte als NOT NULL eingerichtet habe, wenn NULL ein überflüssiger Status wäre. Ähnlich Viele meiner DB-Spalten sind als NOT NULL eingerichtet. Wenn ich diese in eine C # -String einbringe, ist der String leer oder hat einen Wert, aber niemals NULL. Mit anderen Worten, ich initialisiere einen String nur mit NULL wenn null eine Bedeutung hat, die sich von der Bedeutung von String.Empty unterscheidet, und ich finde, dass dieser Fall weniger als üblich ist (aber die Leute hier haben legitime Beispiele für diesen Fall gegeben). ")


Die Verwendung von String.Empty ähnelt nur einer der Möglichkeiten, wie eine Datenbankzeichenfolge definiert wird. Die Verwendung von null, um keinen Wert darzustellen, ist mit einem null-nvarchar viel kongruenter. Ich denke, jeder DBA, der sein Salz wert ist, würde Sie auf neun Arten dumm machen, wenn Sie '' verwenden, um keinen Wert darzustellen.
vfilby

Eigentlich, Greg, hast du es falsch herum verstanden. Es sind die nicht nullbaren Werttypen, die am wenigsten "wie Datenbanktypen funktionieren", da sie niemals eine Null enthalten können und daher niemals einer nullbaren Spalte zugeordnet werden können. Im Vertrag kann jede Zeichenfolge einer beliebigen Varchar-Spalte zugeordnet werden.
Tor Haugen

Sie haben Recht, meine letzte Behauptung war nicht klar genug. Meistens sind meine Datenbankspalten NICHT NULL (da es keinen Unterschied zwischen der Bedeutung von leerer Zeichenfolge und NULL geben würde), daher versuche ich, meine Zeichenfolgen ähnlich zu halten, indem ich niemals Null darin speichere, und das habe ich gemeint.
Greg Smalter

5

Es hängt davon ab, ob.

Müssen Sie feststellen können, ob der Wert fehlt (kann er möglicherweise nicht definiert werden)?

Ist die leere Zeichenfolge ein gültiger Wert für die Verwendung dieser Zeichenfolge?

Wenn Sie beide mit "Ja" beantwortet haben, möchten Sie null verwenden. Andernfalls können Sie den Unterschied zwischen "kein Wert" und "leerer String" nicht erkennen.

Wenn Sie nicht wissen müssen, ob es keinen Wert gibt, ist die leere Zeichenfolge wahrscheinlich sicherer, da Sie damit Nullprüfungen überspringen können, wo immer Sie sie verwenden.



3

Ich setze es entweder auf "" oder null - ich überprüfe es immer mit String.IsNullOrEmpty, also ist beides in Ordnung.

Aber der innere Geek in mir sagt, ich sollte es auf null setzen, bevor ich einen richtigen Wert dafür habe ...



2

Ist es möglich, dass dies eine Fehlervermeidungstechnik ist (ratsam oder nicht ..)? Da "" immer noch eine Zeichenfolge ist, können Sie Zeichenfolgenfunktionen aufrufen, die zu einer Ausnahme führen würden, wenn sie NULL wäre.


1
Das ist die Ausrede, die ich normalerweise höre, die sich nur nach Faulheit anhört. "Ich möchte diesen Wert nicht überprüfen, also nehme ich eine Verknüpfung", scheint es mir.
Vfilby

Ja, ich bin nicht anderer Meinung. Es kann Situationen geben, in denen es hilfreich ist, die Anzahl der Fehlerprüfcodes zu reduzieren, aber Funktionsaufrufe, die keine Auswirkungen haben, sind auch nicht die größten.
Dana the Sane

2

Ich initialisiere sie immer als NULL.

Ich benutze immerstring.IsNullOrEmpty(someString) , um den Wert zu überprüfen.

Einfach.


1

Es hängt von der Situation ab. In den meisten Fällen verwende ich String.Empty, da ich nicht jedes Mal, wenn ich versuche, einen String zu verwenden, Nullprüfungen durchführen möchte. Dies vereinfacht den Code erheblich und es ist weniger wahrscheinlich, dass unerwünschte Abstürze mit NullReferenceException auftreten.

Ich setze die Zeichenfolge nur dann auf null, wenn ich wissen muss, ob sie festgelegt wurde oder nicht und wo eine leere Zeichenfolge gültig ist, um sie festzulegen. In der Praxis finde ich diese Situationen selten.


1

Eine leere Zeichenfolge ist ein Wert (ein Text, der übrigens keine Buchstaben enthält). Null bedeutet kein Wert.

Ich initialisiere Variablen auf null, wenn ich angeben möchte, dass sie nicht auf tatsächliche Werte zeigen oder diese enthalten - wenn die Absicht darin besteht, keinen Wert zu haben.


1

Beachten Sie bei der Wiederholung der Tomalak-Antwort, dass Ihre Variable kein Zeichenfolgenobjekt mehr ist, wenn Sie eine Zeichenfolgenvariable einem Anfangswert von null zuweisen. Gleiches gilt für jedes Objekt in C #. Wenn Sie also versuchen, auf Methoden oder Eigenschaften für Ihre Variable zuzugreifen, und davon ausgehen, dass es sich um ein Zeichenfolgenobjekt handelt, wird die Ausnahme NullReferenceException angezeigt.


1

Null sollte nur in Fällen verwendet werden, in denen ein Wert optional ist. Wenn der Wert nicht optional ist (wie 'Name' oder 'Adresse'), sollte der Wert niemals null sein. Dies gilt sowohl für Datenbanken als auch für POCOs und die Benutzeroberfläche. Null bedeutet "Dieser Wert ist optional und fehlt derzeit."

Wenn Ihr Feld nicht optional ist, sollten Sie es als leere Zeichenfolge initialisieren. Wenn Sie es als null initialisieren, wird Ihr Objekt in einen ungültigen Zustand versetzt (ungültig durch Ihr eigenes Datenmodell).

Persönlich möchte ich lieber, dass Zeichenfolgen nicht standardmäßig nullwertfähig sind, sondern nur dann nullwertfähig, wenn wir eine "Zeichenfolge?" Deklarieren. Obwohl dies auf einer tieferen Ebene vielleicht nicht machbar oder logisch ist; nicht sicher.



0

Ich denke, es gibt keinen Grund, null nicht für einen nicht zugewiesenen Wert (oder an dieser Stelle in einem Programmfluss, der nicht auftritt) zu verwenden. Wenn Sie unterscheiden möchten, gibt es == null. Wenn Sie nur nach einem bestimmten Wert suchen möchten und sich nicht darum kümmern möchten, ob er null oder etwas anderes ist, ist String.Equals ("XXX", MyStringVar) in Ordnung.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.