Pourquoi valide-t-il la concaténation de chaînes nulles sans appeler «null.ToSsortingng ()»?

Ceci est un code C # valide

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

Ce code n’est pas valide

 var wtf = null.ToSsortingng(); // comstackr error 

Pourquoi la première déclaration est-elle valide?

La raison du premier travail:

De MSDN :

Dans les opérations de concaténation de chaînes, le compilateur C # traite une chaîne NULL comme une chaîne vide, mais ne convertit pas la valeur de la chaîne NULL d’origine.

Plus d’informations sur l’ opérateur + binary :

L’opérateur binary + effectue une concaténation de chaîne lorsqu’un ou les deux opérandes sont de type ssortingng.

Si un opérande de concaténation de chaîne est nul, une chaîne vide est substituée. Sinon, tout argument non-chaîne est converti en sa représentation sous forme de chaîne en ToSsortingng méthode virtuelle ToSsortingng héritée de l’object type.

Si ToSsortingng renvoie null , une chaîne vide est remplacée.

La raison de l’erreur en deuxième est:

null (référence C #) – Le mot clé null est un littéral qui représente une référence null, qui ne fait référence à aucun object. null est la valeur par défaut des variables de type référence.

Car l’opérateur + en C # traduit en interne en Ssortingng.Concat , qui est une méthode statique. Et cette méthode arrive à traiter null comme une chaîne vide. Si vous regardez la source de Ssortingng.Concat dans Reflector, vous le verrez:

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

(MSDN le mentionne également: http://msdn.microsoft.com/en-us/library/k9c94ey1.aspx )

D’autre part, ToSsortingng() est une méthode d’instance, que vous ne pouvez pas appeler sur null (quel type doit être utilisé pour null ?).

Le premier échantillon sera traduit en:

 var bob = Ssortingng.Concat("abc123", null, null, null, "abs123"); 

La méthode Concat vérifie l’entrée et traduit null en tant que chaîne vide

Le deuxième échantillon sera traduit en:

 var wtf = ((object)null).ToSsortingng(); 

Donc, une exception de référence null sera générée ici

La première partie de votre code est simplement traitée comme celle de Ssortingng.Concat ,

c’est ce que le compilateur C # appelle lorsque vous ajoutez des chaînes. ” abc" + null est traduit en Ssortingng.Concat("abc", null) ,

et en interne, cette méthode remplace null par Ssortingng.Empty . C’est pourquoi votre première partie de code ne génère aucune exception. c’est comme

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

Et dans la deuxième partie de votre code lève une exception car «null» n’est pas un object, le mot clé null est un littéral qui représente une référence null , une référence ne faisant référence à aucun object. null est la valeur par défaut des variables de type référence.

Et ‘ ToSsortingng() ‘ est une méthode qui peut être appelée par une instance d’un object mais pas par un littéral.

Dans le framework COM qui précédait .net, il était nécessaire pour toute routine qui recevait une chaîne de la libérer lorsqu’elle était terminée. Comme il était très courant que des chaînes vides soient passées dans des routines et que la tentative de “libérer” un pointeur nul était définie comme une opération légitime, Microsoft a décidé de faire en sorte qu’une chaîne vide représente une chaîne vide.

Pour permettre une certaine compatibilité avec COM, de nombreuses routines dans .net interpréteront un object nul comme une représentation légale sous la forme d’une chaîne vide. Avec quelques légères modifications .net et ses langages (permettant notamment aux membres d’instance d’indiquer “ne pas appeler en tant que virtuel”), Microsoft aurait pu faire que null objects null de type déclaré Ssortingng se comportent encore plus comme des chaînes vides. Si Microsoft avait fait cela, il aurait également dû faire en Nullable que Nullable fonctionne quelque peu différemment (de manière à autoriser Nullable quelque chose qu’il devrait faire à tout moment) et / ou définir un type NullableSsortingng interchangeable avec Ssortingng , mais qui ne considérerait pas un null comme une chaîne vide valide.

En l’occurrence, il existe certains contextes dans lesquels un null sera considéré comme une chaîne vide légitime et d’autres non. Ce n’est pas une situation terriblement utile, mais une situation que les programmeurs doivent connaître. En général, les expressions de la forme ssortingngValue.someMember échoueront si ssortingngValue est null , mais la plupart des méthodes et des opérateurs qui acceptent des chaînes en tant que parameters considéreront null comme une chaîne vide.

'+' est un opérateur infixe. Comme tout opérateur, il appelle vraiment une méthode. Vous pouvez imaginer une version non infixe "wow".Plus(null) == "wow"

Le réalisateur a choisi quelque chose comme ça …

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

Donc .. votre exemple devient

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

qui est la même que

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

À aucun moment, null ne devient une chaîne. Donc, null.ToSsortingng() n’est pas différent de null.VoteMyAnswer() . 😉

Je suppose parce que c’est un littéral qui ne se réfère à aucun object. ToSsortingng() besoin d’un object .

Quelqu’un a dit dans ce fil de discussion que vous ne pouvez pas créer de chaîne à partir de rien. (ce qui est une bonne phrase à mon avis). Mais oui, vous pouvez :-), comme le montre l’exemple suivant:

 var x = null + (ssortingng)null; var wtf = x.ToSsortingng(); 

fonctionne bien et ne jette aucune exception. La seule différence est que vous devez convertir l’un des caractères NULL en une chaîne – si vous supprimez la dissortingbution (chaîne) , l’exemple est toujours compilé, mais génère une exception à l’exécution: “L’opérateur +” est ambigu sur les opérandes de tapez ‘‘ et ‘‘ “.

NB Dans l’exemple de code ci-dessus, la valeur de x n’est pas nulle comme on peut s’y attendre, c’est en fait une chaîne vide après avoir lancé l’un des opérandes dans une chaîne.


Un autre fait intéressant est que, dans C # / .NET, la façon dont null est traité n’est pas toujours la même si vous considérez différents types de données. Par exemple:

 int? x = 1; // ssortingng x = "1"; x = x + null + null; Console.WriteLine((x==null) ? "" : x.ToSsortingng()); 

Concernant la 1ère ligne de l’extrait de code: Si x est une variable entière nullable (c’est-à-dire int? ) Contenant la valeur 1 , alors vous obtenez le résultat . Si c’est une chaîne (comme indiqué dans le commentaire) avec la valeur "1" , alors vous obtenez "1" arrière plutôt que .

NB Aussi intéressant: Si vous utilisez var x = 1; pour la première ligne, vous obtenez une erreur d’exécution. Pourquoi? Parce que l’affectation transformera la variable x dans le type de données int , qui n’est pas nullable. Le compilateur n’assume pas int? ici, et donc échoue dans la 2ème ligne où null est ajouté.

L’ajout de null à une chaîne est simplement ignoré. null (dans votre deuxième exemple) n’est pas une instance d’un object, il n’a donc même pas de méthode ToSsortingng() . C’est juste un littéral.

Parce qu’il n’y a pas de différence entre ssortingng.Empty et null lorsque vous concatnez des chaînes. Vous pouvez également transmettre null à ssortingng.Format . Mais vous essayez d’appeler une méthode sur null , ce qui entraînerait toujours une NullReferenceException et génère donc une erreur de compilation.
Si, pour une raison quelconque, vous voulez vraiment le faire, vous pouvez écrire une méthode d’extension, qui vérifie la valeur null puis renvoie ssortingng.Empty . Mais une telle extension ne devrait être utilisée que lorsque cela est absolument nécessaire (à mon avis).

Comme général: il peut être ou non valide en acceptant null comme paramètre en fonction de la spécification, mais il est toujours invalide d’appeler une méthode sur null.


C’est et autre sujet pourquoi les opérandes de l’opérateur + peuvent être nuls en cas de chaînes. C’est quelque chose de VB (désolé les gars) pour faciliter la vie des programmeurs, ou supposer que le programmeur ne peut pas gérer les valeurs NULL. Je suis complètement en désaccord avec cette spécification. “inconnu” + “n’importe quoi” devrait être encore “inconnu” …