Warum gibt Convert.ToString (null) einen anderen Wert zurück, wenn Sie null umwandeln?

116
Convert.ToString(null)

kehrt zurück

null

Wie ich erwartet habe.

Aber

Convert.ToString(null as object)

kehrt zurück

""

Warum sind diese unterschiedlich?

John MacIntyre
quelle

Antworten:

143

Hier kommen 2 Überladungen ToStringins Spiel

Convert.ToString(object o);
Convert.ToString(string s);

Der C # -Compiler versucht im Wesentlichen, die spezifischste Überladung auszuwählen, die mit der Eingabe funktioniert. Ein nullWert kann in einen beliebigen Referenztyp konvertiert werden. In diesem Fall stringist es spezifischer als objectund daher wird es als Gewinner ausgewählt.

In der haben null as objectSie den Typ des Ausdrucks als verfestigt object. Dies bedeutet, dass es nicht mehr mit der stringÜberladung kompatibel ist und der Compiler die objectÜberladung auswählt, da es die einzige verbleibende kompatible ist.

Die wirklich haarigen Details, wie dieses Binden funktioniert, werden in Abschnitt 7.4.3 der C # -Sprachenspezifikation behandelt.

JaredPar
quelle
15
OK. Es wird also eine Überlastung anstelle der anderen verwendet. Macht Sinn. Aber sollten nicht beide Überladungen dasselbe zurückgeben? +1 übrigens.
John MacIntyre
2
@ JohnMacIntyre - Das hängt vom Entwicklungsteam ab, nicht vom Compiler.
JonH
8
@JohnMacIntyre Wenn Sie sich die Implementierung ansehen, handelt Convert.ToString(string)es sich nur um eine Identitätsfunktion, während Sie Convert.ToString(object)tatsächlich einen schwer zu verfolgenden Pfad durchlaufen. Auf einen Blick würde ich zustimmen, dass sie dasselbe zurückgeben sollten, aber die konvertierbare Schicht der BCL ist nicht sehr gut bekannt und es gibt möglicherweise einen guten Grund für den Unterschied (ich bin allerdings skeptisch)
JaredPar
Ich bin hierher gekommen, um zu suchen, wie man ein Nullobjekt in eine Nullzeichenfolge konvertiert. Die Antwort für andere Sucher ist (string)null, oder wenn Ihr Objekt o heißt, dann(string)o
rayzinnz
65

In Anlehnung an JaredPars hervorragende Antwort auf die Überlastungsauflösung bleibt die Frage: "Warum wird Convert.ToString(string)null zurückgegeben, aber Convert.ToString(object)zurückgegeben string.Empty?"

Und die Antwort auf diese Frage ist ... weil die docs sagen so :

Convert.ToString (Zeichenfolge) gibt "die angegebene Zeichenfolgeninstanz zurück; es wird keine tatsächliche Konvertierung durchgeführt."

Convert.ToString (Objekt) gibt "die Zeichenfolgendarstellung des Werts oder String.Empty zurück, wenn der Wert null ist".

BEARBEITEN: Ob dies ein "Fehler in der Spezifikation", ein "sehr schlechtes API-Design", "warum wurde es so spezifiziert" usw. ist - ich werde einige Gründe untersuchen, warum ich es nicht sehe es als große Sache.

  1. System.Convertverfügt über Methoden zum Konvertieren jedes Basistyps in sich selbst . Dies ist seltsam - da keine Konvertierung erforderlich oder möglich ist, geben die Methoden nur den Parameter zurück. Convert.ToString(string)verhält sich gleich. Ich nehme an, diese sind hier für Codegenerierungsszenarien.
  2. Convert.ToString(object)hat 3 Möglichkeiten, wenn bestanden null. Werfen, null zurückgeben oder string zurückgeben. Leer. Werfen wäre schlecht - doppelt so unter der Annahme, dass diese für generierten Code verwendet werden. Wenn Sie null zurückgeben, muss Ihr Anrufer eine Nullprüfung durchführen - wiederum keine gute Wahl für den generierten Code. String zurückgeben. Leer scheint eine vernünftige Wahl zu sein. Der Rest System.Convertbefasst sich mit Werttypen, die einen Standardwert haben.
  3. Es ist fraglich, ob die Rückgabe von null "korrekter" ist, aber string.Empty ist definitiv benutzerfreundlicher. Ändern Convert.ToString(string)bedeutet, die Regel "Keine tatsächliche Konvertierung" zu brechen. Da System.Convertes sich um eine statische Dienstprogrammklasse handelt, kann jede Methode logisch als ihre eigene behandelt werden. Es gibt nur sehr wenige reale Szenarien, in denen dieses Verhalten "überraschend" sein sollte. Lassen Sie also die Benutzerfreundlichkeit die (mögliche) Korrektheit gewinnen.
Mark Brackett
quelle
Ist es fair zu sagen, dass dies ein Fehler in der Spezifikation ist?
John MacIntyre
3
das antwortet nicht, warum es so ist. Zu sagen, dass es sich so verhält, weil dokumentiert ist, dass es sich so verhält, ist tautologisch.
CodesInChaos
2
@ JohnMacIntyre IMO ist es fair zu sagen, dass es sehr schlechtes API-Design ist.
CodesInChaos
7
@CodeInChaos - keine Tautologie, es sei denn, Sie gehen davon aus, dass die Dokumente basierend auf beobachtbarem Verhalten nach der Entwicklung der BCL geschrieben wurden. Das wäre eine seltsame Annahme, denke ich. IOW, es ist nicht "dokumentiert, um sich so zu verhalten", es ist "dokumentiert, dass es sich so verhält" - dh es ist " angegeben, um sich so zu verhalten".
Mark Brackett
8
Es verschiebt nur die Frage zu "Warum wurde angegeben, um sich so zu verhalten"
CodesInChaos