¿Cuál es el punto de la cadena? Propiedad vacía

35

¿Por qué se string foo = string.Emptyincluyó la propiedad en el BCL? Parece más detallado y no más claro que simplemente usar una cadena vacía ( string foo = "")

Tom Squires
fuente
66
Nitpick: no es parte del lenguaje. Es parte de la BCL. VB.NET y F # pueden usarlo, así como cualquier otro lenguaje .NET.
Oded
19
Porque de lo contrario, no podrías hacer cosas malas como typeof(string).GetField("Empty").SetValue(null, " ");;)
Mason Wheeler
1
@MasonWheeler - Las alegrías de la reflexión. Para el mal real, necesitas introspección, ¿eh?
Oded
1
@MasonWheeler, +1. ¡Oh Dios, las gafas, no hacen nada!]
Machado
1
@MasonWheeler Eso es puro, destilado mal. Me encanta esto. Pregunta si te interesa: ¿no sería más seguro (y con un rendimiento decente) escribirlo como public static string Empty { get { return string.Intern(""); } }?
Jesse C. Slicer

Respuestas:

55

Solo puedo suponer aquí:

string.Emptyse ha definido para que sea explícito: cuando se inicializa una cadena, puede no quedar claro por el contexto que de ""hecho se entiende explícitamente como un inicializador (en lugar de nulldecir " "o simplemente como un marcador de posición durante la prueba). Usar string.Emptyes una respuesta definitiva a ese tipo de acertijo.

También puede ser un retroceso a C: una cadena vacía en C no es una cadena vacía. Es una matriz de caracteres cuyo primer carácter es nulo (por lo tanto, vacío), que no es lo mismo que C #. Mi punto aquí es que en diferentes idiomas representaría una cadena vacía de diferentes maneras (y pueden tener diferentes significados), ya que tiene una string.Emptygran ambigüedad.

A diferencia de lo que otros dicen sobre varios objetos, esto no es un problema, ya que cualquier cadena literal se internará en la compilación. Esto incluye el valor de string.Empty- "". Cada vez que cualquiera de estos se repita en el código, el objeto se recuperará del grupo interno. Esto es cierto por dominio de aplicación .

Oded
fuente
55
+1 por ser la única respuesta correcta hasta ahora.
psr
Es posible que algunos idiomas ni siquiera tengan un literal de cadena vacío. Aparentemente, Pascal estándar no lo hizo.
dan04
2
"una cadena vacía en C no es una cadena vacía", pero aún así, si escribes "", obtienes {'\0'}, por lo que no habría diferencia entre un literal de cadena vacía y alguna otra forma indirecta de definirlo.
desvío
14

No estoy 100% seguro de las fuentes donde aprendí esto, pero algunos de los puntos para usarlo incluyen:

  • Cada cadena en un ensamblado .NET es única, por lo que tener

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

    da como resultado 2 cadenas en el ensamblaje de salida ya que las cadenas son inmutables. Tener ambas referencias string.Emptyreduce el tamaño del ensamblaje.

  • Claridad. Cuando te encuentras con string.Emptyla intención, está claro que se supone que es una cadena vacía. Pero si se encuentra, foo = ""¿el programador eliminó el contenido de la cadena durante la prueba y olvidó agregarlo nuevamente, o se supone que debe ser así?
Agent_9191
fuente
1
Parecería un comportamiento extraño mantener dos cadenas idénticas en la memoria. ¿De hecho es eso lo que se hace?
Plataforma
36
De hecho, se hace lo contrario: se llama internamiento de cadenas (más precisamente, internación de literales). Sé con certeza que se hace en Java y Python, y estoy bastante seguro de que también es el caso en los lenguajes .NET. Por supuesto, solo puede ocurrir en el ámbito de una sola unidad de traducción, por lo que a menos que el cargador dinámico unifique dichos datos, puede terminar con una cadena vacía por archivo de programa. Todavía no mucho.
99
@delnan tiene toda la razón. ""/ string.Emptyson internados y solo se creará un objeto.
Oded
11
@Andy: todos los literales de cadena están internados en .NET. No todas las cuerdas. Las cadenas creadas mediante programación no se internan por defecto. Ver String.Intern en MSDN.
Oded
3
@Oded et alia: en realidad ninguno de ustedes tiene razón. Primero, los literales son internados dentro de un conjunto, pero no necesariamente entre conjuntos . En segundo lugar, si la cadena vacía está internada o no en los ensamblajes es un detalle de implementación; Algunas versiones de CLR sí y otras no. Hay un enlace a mi artículo sobre este hecho en una de las otras respuestas; Véalo para los detalles.
Eric Lippert
2

No se creará ningún objeto para string.Empty. El uso ""creará un objeto que probablemente provenga del grupo interno de cadenas.

En el pasado, la gente ha realizado pruebas y String.Emptysale un poco más rápido, pero es una micro optimización.

String.Empty es esto:

//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 = ""; 
Jon Raynor
fuente
2
¿Entonces tu punto es ...?
1
El punto es String.Empty es básicamente una constante para "". Encuentre al autor de String.cs para obtener un significado más profundo. :)
Jon Raynor
0

Es una cuestión de optimización del consumo de memoria y una optimización de la comparación de cadenas. Cada vez que utiliza una cadena vacía en su aplicación, está asignando un objeto de cadena que contiene 0 caracteres. En cuanto a la comparación de cadenas, se puede hacer comparando referencias (punteros) en lugar de carácter por carácter, que es más rápido incluso para cadenas vacías.

Si usa muchas veces la misma cadena en su aplicación, puede usar el mismo tipo de mecanismo llamando a String.Intern () con su cadena. Pero si usa cada cadena solo una vez, solo usará más memoria.

Entonces, String.Empty es solo una optimización de casos especiales que vale la pena hacer para la mayoría de las aplicaciones .Net, por eso se integró en el BCL.

Para más detalles sobre este tema, recomiendo leer la publicación del blog de Eric Lippert .

También debe echar un vistazo a esta documentación a la que hace referencia su publicación de blog.

rold2007
fuente
44
Las respuestas de solo enlace no son buenas respuestas. Si Eric alguna vez reorganiza su blog, esta respuesta será inútil. Por favor resuma el post aquí, así que tenemos toda la información a mano.
ChrisF
77
@ChrisF: No puedo reorganizar el blog. Eso sería un cambio radical, y ya sabes lo que siento por ellos.
Eric Lippert
1
@EricLippert - Me da cuenta de que desea nunca se hace, sin embargo, sólo enlace respuestas no son buenas respuestas y tenemos que animar a la gente a darse cuenta de eso.
ChrisF
3
@EricLippert No se trata solo de enlaces efímeros. Aquí también se trata de la cortesía con los lectores, debe haber al menos suficiente contenido directamente en la respuesta para que los lectores puedan formarse una opinión sobre si seguir el enlace. Y la respuesta debería tener sentido incluso en una copia fuera de línea de SE.
Gilles 'SO- deja de ser malvado'