Pourquoi Convert.ToString (null) renvoie-t-il une valeur différente si vous convertissez null?

116
Convert.ToString(null)

Retour

null

Comme je l'attendais.

Mais

Convert.ToString(null as object)

Retour

""

Pourquoi sont-ils différents?

John MacIntyre
la source

Réponses:

143

Il y a 2 surcharges ToStringqui entrent en jeu ici

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

Le compilateur C # essaie essentiellement de choisir la surcharge la plus spécifique qui fonctionnera avec l'entrée. Une nullvaleur est convertible en n'importe quel type de référence. Dans ce cas, il stringest plus spécifique que objectet par conséquent, il sera choisi comme gagnant.

Dans le, null as objectvous avez solidifié le type de l'expression en tant que object. Cela signifie qu'il n'est plus compatible avec la stringsurcharge et que le compilateur sélectionne la objectsurcharge car c'est la seule compatible qui reste.

Les détails vraiment épineux du fonctionnement de cette rupture de cravate sont traités dans la section 7.4.3 de la spécification du langage C #.

JaredPar
la source
15
D'accord. Il utilise donc une surcharge au lieu de l'autre. Logique. Mais les deux surcharges ne devraient-elles pas renvoyer la même chose? +1 btw.
John MacIntyre
2
@JohnMacIntyre - Cela dépend de l'équipe de développement et non du compilateur.
JonH
8
@JohnMacIntyre Si vous regardez l'implémentation de Convert.ToString(string)c'est juste une fonction d'identité alors Convert.ToString(object)qu'il passe par un chemin plus difficile à suivre. En un coup d'œil, je serais d'accord pour dire qu'ils devraient retourner la même chose, mais la couche convertible de la BCL n'est pas quelque chose que je connais très bien et il est possible qu'il y ait une bonne raison à la différence (je suis sceptique cependant)
JaredPar
Je suis venu ici pour savoir comment convertir un objet nul en une chaîne nulle. La réponse pour les autres chercheurs est (string)null, ou si votre objection s'appelle o, alors(string)o
rayzinnz
65

Suite à l'excellente réponse de résolution de surcharge de JaredPar - la question reste "pourquoi Convert.ToString(string)retourne null, mais Convert.ToString(object)retourne string.Empty"?

Et la réponse est ... parce que les documents disent donc :

Convert.ToString (string) renvoie "l'instance de chaîne spécifiée; aucune conversion réelle n'est effectuée."

Convert.ToString (object) renvoie «la représentation sous forme de chaîne de valeur, ou String.Empty si value est null».

EDIT: Quant à savoir s'il s'agit d'un "bogue dans la spécification", "très mauvaise conception d'API", "pourquoi a-t-il été spécifié comme ça", etc. - Je vais essayer de trouver une raison pour laquelle je ne vois pas c'est un gros problème.

  1. System.Converta des méthodes pour convertir chaque type de base en lui-même . C'est étrange - puisqu'aucune conversion n'est nécessaire ou possible, les méthodes finissent par renvoyer simplement le paramètre. Convert.ToString(string)se comporte de la même manière. Je suppose que ce sont là pour les scénarios de génération de code.
  2. Convert.ToString(object)a 3 choix une fois passé null. Lance, renvoie null ou renvoie une chaîne. Lancer serait mauvais - doublement avec l'hypothèse qu'ils sont utilisés pour le code généré. Le retour de null nécessite que votre appelant fasse une vérification de null - encore une fois, ce n'est pas un excellent choix dans le code généré. Renvoyer la chaîne. Vide semble un choix raisonnable. Le reste System.Converttraite des types de valeur - qui ont une valeur par défaut.
  3. On peut se demander si le retour de null est plus "correct", mais string.Empty est certainement plus utilisable. Changer Convert.ToString(string)signifie enfreindre la règle "pas de conversion réelle". Puisqu'il System.Converts'agit d'une classe d'utilité statique, chaque méthode peut être logiquement traitée comme la sienne. Il y a très peu de scénarios du monde réel où ce comportement devrait être "surprenant", laissez donc l'utilisabilité l'emporter sur la (possible) correction.
Mark Brackett
la source
Est-il juste de dire que c'est un bogue dans la spécification?
John MacIntyre
3
cela ne répond pas pourquoi c'est comme ça. Dire qu'il se comporte comme ça parce qu'il est documenté qu'il se comporte comme ça est tautologique.
CodesInChaos
2
@JohnMacIntyre IMO, il est juste de dire que c'est une très mauvaise conception d'API.
CodesInChaos
7
@CodeInChaos - pas une tautologie, sauf si vous supposez que les documents sont écrits en fonction d'un comportement observable après le développement de la BCL. Ce serait une hypothèse étrange, je pense. IOW, il n'est pas "documenté pour se comporter comme ceci", il est "documenté qu'il se comportera comme ceci" - c'est-à-dire qu'il est " spécifié pour se comporter comme ceci".
Mark Brackett
8
Cela ne fait que déplacer la question sur "pourquoi a-t-il été spécifié de se comporter comme ça"
CodesInChaos