[c#] Warum ist es zulässig, Null-Strings zu verketten, aber nicht "null.ToString ()" aufzurufen?


Answers

Weil der Operator + in C # intern in String.Concat übersetzt String.Concat , was eine statische Methode ist. Und diese Methode behandelt null als eine leere Zeichenfolge. Wenn Sie sich die Quelle von String.Concat in Reflector String.Concat , sehen Sie String.Concat :

// while looping through the parameters
strArray[i] = (str == null) ? Empty : str;
// then concatenate that string array

(MSDN erwähnt es auch: http://msdn.microsoft.com/en-us/library/k9c94ey1.aspx )

Auf der anderen Seite ist ToString() eine Instanzmethode, die Sie nicht auf null aufrufen null (welcher Typ sollte für null ?).

Question

Dies ist ein gültiger C # -Code

var bob = "abc" + null + null + null + "123";  // abc123

Dies ist kein gültiger C # -Code

var wtf = null.ToString(); // compiler error

Warum ist die erste Aussage gültig?




Der erste Teil Ihres Codes wird nur so behandelt wie in String.Concat ,

Das ist, was der C # -Compiler beim Hinzufügen von Zeichenfolgen aufruft. " abc" + null wird in String.Concat("abc", null) ,

und intern ersetzt diese Methode null durch String.Empty . Aus diesem Grund ist der erste Teil des Codes keine Ausnahme. Es ist einfach so

var bob = "abc" + string.Empty + string.Empty + string.Empty + "123";  //abc123

Und im zweiten Teil Ihres Codes wird die Exception ausgelöst, weil 'null' kein Objekt ist. Das Schlüsselwort 'null' ist ein Literal, das eine Nullreferenz darstellt , eine, die sich nicht auf ein Objekt bezieht. null ist der Standardwert von Variablen vom Referenztyp.

Und ' ToString() ' ist eine Methode, die von einer Instanz eines Objekts, aber nicht von einem Literal aufgerufen werden kann.




Jemand hat in diesem Diskussionsfaden gesagt, dass man keine Schnur aus dem Nichts machen kann. (was ein schöner Satz ist, wie ich denke). Aber ja - du kannst :-), wie das folgende Beispiel zeigt:

var x = null + (string)null;     
var wtf = x.ToString();

funktioniert gut und wirft keine Ausnahme. Der einzige Unterschied besteht darin, dass Sie einen der Nullen in einen String umwandeln müssen - wenn Sie den ( String- ) Cast entfernen, wird das Beispiel trotzdem kompiliert, aber es wird eine Laufzeitausnahme ausgelöst: "Operator '+' ist bei Operanden von mehrdeutig Geben Sie '<null>' und '<null>' ein.

Hinweis: In dem obigen Codebeispiel ist der Wert von x nicht Null, wie Sie vielleicht erwarten, es handelt sich tatsächlich um eine leere Zeichenfolge, nachdem Sie einen der Operanden in eine Zeichenfolge umgewandelt haben.

Eine weitere interessante Tatsache ist, dass in C # / .NET die Art, wie null behandelt wird, nicht immer gleich ist, wenn Sie unterschiedliche Datentypen betrachten. Beispielsweise:

int? x = 1;  //  string x = "1";
x = x + null + null;
Console.WriteLine((x==null) ? "<null>" : x.ToString());

Beachten Sie die erste Zeile des Code-Snippets: Wenn x eine nullbare Ganzzahlvariable (dh int? ) Mit dem Wert 1 , erhalten Sie das Ergebnis <null> zurück. Wenn es sich um eine Zeichenfolge (wie im Kommentar gezeigt) mit dem Wert "1" , erhalten Sie "1" zurück statt <null> .

NB Auch interessant: Wenn Sie var x = 1; Für die erste Zeile erhalten Sie einen Laufzeitfehler. Warum? Weil die Zuweisung die Variable x in den Datentyp int umwandeln wird, der nicht nullbar ist. Der Compiler nimmt nicht int? hier, und daher in der zweiten Zeile fehlt, wo null hinzugefügt wird.




Weil es keinen Unterschied zwischen string.Empty und null wenn Sie Strings dekonstruieren. Sie können string.Format auch in string.Format . Sie versuchen jedoch, eine Methode für null aufzurufen, was immer zu einer NullReferenceException und daher einen Compilerfehler generiert.
Wenn Sie es aus irgendeinem Grund wirklich tun möchten, könnten Sie eine Erweiterungsmethode schreiben, die auf null prüft und dann string.Empty . Aber eine solche Erweiterung sollte nur dann benutzt werden, wenn sie absolut notwendig ist (meiner Meinung nach).




'+' ist ein Infix-Operator. Wie jeder Operator ruft es wirklich eine Methode auf. Sie könnten sich eine Nicht-Infix-Version vorstellen "wow".Plus(null) == "wow"

Der Implementierer hat sich für so etwas entschieden ...

class String
{
  ...
  String Plus(ending)
  {
     if(ending == null) return this;
     ...
  }
} 

Also ... dein Beispiel wird

var bob = "abc".Plus(null).Plus(null).Plus(null).Plus("123");  // abc123

Das ist das Gleiche wie

var bob = "abc".Plus("123");  // abc123

Zu keinem Zeitpunkt wird aus Null eine Zeichenfolge. Also ist null.ToString() nicht anders als null.VoteMyAnswer() . ;)




Links