Quel est le point de la propriété string.Empty


35

Pourquoi la propriété était-elle string foo = string.Emptyincluse dans la BCL? Cela semble plus détaillé et plus clair que de simplement utiliser une chaîne vide ( string foo = "")


6
Nitpick: Cela ne fait pas partie de la langue. Cela fait partie de la BCL. VB.NET et F # peuvent l’utiliser, ainsi que tous les autres langages .NET.
Oded

19
Parce que sinon, vous ne pourriez pas faire de mauvaises choses comme typeof(string).GetField("Empty").SetValue(null, " ");;)
Mason Wheeler

1
@MasonWheeler - Les joies de la réflexion. Pour le vrai mal, vous avez besoin d'introspection, hein?
Oded

1
@MasonWheeler, +1. Oh mon dieu, les lunettes, ils ne font rien!]
Machado

1
@MasonWheeler C'est du mal pur et distillé. J'aime cela. Question si cela vous intéresse: ne serait-il pas plus sûr (et décemment performant) de l'avoir écrit comme public static string Empty { get { return string.Intern(""); } }?
Jesse C. Slicer

Réponses:


55

Je ne peux que supposer ici:

string.Emptya été défini pour être explicite - lors de l’initialisation d’une chaîne, il se peut que le contexte ne soit pas clairement défini ""comme un initialiseur (au lieu de nullou " "comme ou tout simplement comme un espace réservé pendant les tests). Utiliser string.Emptyest une réponse définitive à ce genre d’énigme.

Il peut également s'agir d'un retour en arrière - une chaîne vide en C n'est pas une chaîne vide. C'est un tableau de caractères dont le premier caractère est null (donc vide), ce qui n'est pas la même chose que C #. Mon point ici est que, dans différentes langues, vous représenteriez une chaîne vide de différentes manières (et peuvent avoir différentes significations), ce qui string.Emptyévite une telle ambiguïté.

Contrairement à ce que d’autres disent à propos de plusieurs objets - ce n’est pas un problème car tout littéral de chaîne sera interné lors de la compilation. Cela inclut la valeur de string.Empty- "". Chaque fois que l'un ou l'autre de ces éléments est répété dans le code, l'objet sera extrait du pool interne. Cela est vrai par domaine d'application .


5
+1 pour être la seule réponse correcte à ce jour.
psr

Certaines langues peuvent même ne pas avoir de littéral de chaîne vide. Apparemment, le Pascal standard n'a pas.
dan04

2
"une chaîne vide en C n'est pas une chaîne vide" - mais néanmoins, si vous écrivez "", vous obtenez {'\0'}, il n'y aurait donc aucune différence entre un littéral de chaîne vide et un autre moyen détourné de le définir.
Détly

14

Je ne suis pas sûr à 100% des sources où j'ai appris cela, mais voici quelques-uns des avantages de son utilisation:

  • Chaque chaîne dans un assemblage .NET est unique, donc avoir

    string foo = "";
    string bar = "";

    résulte en 2 chaînes dans l'assemblage de sortie, car les chaînes sont immuables. Avoir les deux références string.Emptyréduit la taille de l'assemblage.

  • Explicitation. Lorsque vous tombez sur string.Emptyl'intention, il est clair qu'il s'agit d'une chaîne vide. Mais si vous rencontrez foo = "", le programmeur a-t-il supprimé le contenu de la chaîne lors des tests et oublié de le rajouter, ou est-ce censé être ainsi?

1
Cela semblerait être un comportement étrange pour lui de garder deux chaînes identiques en mémoire. Est-ce bien ce qui est fait?
Rig

36
En fait, c'est l'inverse qui est fait: cela s'appelle interning string (plus précisément interning littéral). Je sais avec certitude que cela est fait en Java et en Python, et je suis à peu près sûr que c'est également le cas dans les langages .NET. Bien entendu, cela ne peut se produire que dans le cadre d'une seule unité de traduction. Par conséquent, à moins que le chargeur dynamique unifie de telles données, vous risquez de vous retrouver avec une chaîne vide par fichier de programme. Toujours pas terriblement beaucoup.

9
@Delnan a absolument raison. ""/ string.Emptysont internés et un seul objet sera créé.
Oded

11
@Andy - Tous les littéraux de chaîne sont internés dans .NET. Pas toutes les chaînes. Les chaînes créées par programme ne sont pas internées par défaut. Voir String.Intern sur MSDN.
Oded

3
@Oded et alia: En fait, aucun d'entre vous n'a exactement raison. Premièrement, les littéraux sont internes à un assemblage, mais pas nécessairement d' un assemblage à l'autre . Deuxièmement, le fait que la chaîne vide soit internée ou non dans les assemblages est un détail d'implémentation; certaines versions du CLR le font et d'autres pas. Il existe un lien vers mon article à ce sujet dans l'une des autres réponses; voir pour les détails.
Eric Lippert

2

Aucun objet ne sera créé pour string.Empty. Utiliser ""créera un objet qui proviendra probablement du pool interne de chaînes.

Auparavant, les gens String.Emptyeffectuaient des tests et sortaient un peu plus vite, mais c’est une micro-optimisation.

String.Empty est la suivante:

//The Empty constant holds the empty string value.   
//We need to call the String constructor so that the compiler doesn't mark 
//this as a literal.   
//Marking this as a literal would mean that it doesn't show up as a field 
//which we can access from native.  
public static readonly String Empty = ""; 

2
Donc, votre point est ...?

1
Le point est String.Empty est fondamentalement une constante pour "". Trouvez l'auteur de String.cs pour un sens plus profond. :)
Jon Raynor

0

Il s’agit d’optimiser la consommation de mémoire et d’optimiser la comparaison de chaînes. Chaque fois que vous utilisez une chaîne vide dans votre application, vous allouez un objet chaîne contenant 0 caractères. Comme pour la comparaison de chaînes, il est possible de comparer les références (pointeurs) au lieu de caractère par caractère, ce qui est plus rapide, même pour les chaînes vides.

Si vous utilisez plusieurs fois la même chaîne dans votre application, vous pouvez utiliser le même type de mécanisme en appelant String.Intern () avec votre chaîne. Mais si vous utilisez chaque chaîne une seule fois, vous n’utiliserez plus que de la mémoire.

Donc, String.Empty n’est qu’une optimisation de cas particulier qui vaut la peine d’être appliqué à la plupart des applications .Net, c’est pourquoi il a été intégré dans le BCL.

Pour plus de détails sur ce sujet, je vous recommande vivement de lire le blog d'Eric Lippert .

Vous devriez également jeter un coup d'oeil à cette documentation référencée par son article de blog.


4
Lier uniquement les réponses ne donne pas de bonnes réponses. Si Eric réorganise son blog, cette réponse deviendra inutile. Veuillez résumer le message ici pour que nous ayons toutes les informations en main.
ChrisF

7
@ChrisF: Je ne peux jamais réorganiser le blog. Ce serait un changement radical et vous savez ce que je ressens à ce sujet.
Eric Lippert

1
@ EricLippert - Je me rends compte que vous ne feriez jamais cela, cependant, les réponses de lien uniquement ne sont pas de bonnes réponses et nous devons encourager les gens à s'en rendre compte.
ChrisF

3
@EricLippert Il ne s'agit pas uniquement de liens éphémères. Ici, il est également question de politesse pour les lecteurs. Il devrait y avoir au moins assez de contenu directement dans la réponse pour que les lecteurs puissent se faire une opinion sur l'opportunité de suivre le lien. Et la réponse devrait avoir un sens, même dans une copie hors ligne de SE.
Gilles 'SO- arrête d'être méchant'
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.