¿Cuál es la diferencia entre String.Empty y “” (cadena vacía)?

En .NET, ¿cuál es la diferencia entre String.Empty y "" , y son intercambiables, o hay alguna referencia subyacente o problemas de localización en torno a la igualdad que String.Empty garantizará que no haya ningún problema?

En .NET anterior a la versión 2.0, "" crea un objeto mientras que string.Empty no crea ref de objeto, lo que hace que string.Empty sea ​​más eficiente.

En la versión 2.0 y posteriores de .NET, todas las apariciones de "" referencia al mismo literal de cadena, lo que significa que "" es equivalente a .Empty , pero aún no tan rápido como .Length == 0 .

.Length == 0 es la opción más rápida, pero .Empty genera un código ligeramente más limpio.

Consulte la especificación .NET para obtener más información .

¿Cuál es la diferencia entre String.Empty y “”, y son intercambiables?

string.Empty es un campo de solo lectura, mientras que "" es una constante de tiempo de comstackción. Los lugares donde se comportan de manera diferente son:

Valor de parámetro predeterminado en C # 4.0 o superior

 void SomeMethod(int ID, string value = string.Empty) // Error: Default parameter value for 'value' must be a compile-time constant { //... implementation } 

Expresión de caso en statement de cambio

 string str = ""; switch(str) { case string.Empty: // Error: A constant value is expected. break; case "": break; } 

Argumentos de los atributos

 [Example(String.Empty)] // Error: An attribute argument must be a constant expression, typeof expression // or array creation expression of an attribute parameter type 

Las respuestas anteriores eran correctas para .NET 1.1 (observe la fecha de la publicación que vinculó: 2003). A partir de .NET 2.0 y posterior, esencialmente no hay diferencia. El JIT terminará haciendo referencia al mismo objeto en el montón de todos modos.

De acuerdo con la especificación C #, sección 2.4.4.5: http://msdn.microsoft.com/en-us/library/aa691090(VS.71).aspx

Cada cadena literal no da necesariamente como resultado una nueva instancia de cadena. Cuando dos o más literales de cadena que son equivalentes de acuerdo con el operador de igualdad de cadena (Sección 7.9.7) aparecen en el mismo ensamblado, estos literales de cadena hacen referencia a la misma instancia de cadena.

Alguien incluso menciona esto en los comentarios de la publicación de Brad Abram

En resumen, el resultado práctico de “” vs. String.Empty es nulo. El JIT lo resolverá al final.

He descubierto, personalmente, que el JIT es mucho más inteligente que yo, así que trato de no ser demasiado inteligente con optimizaciones de microcomstackción como esa. El JIT se desplegará para () bucles, eliminará el código redundante, los métodos en línea, etc. mejor y en momentos más apropiados de lo que I o el comstackdor de C # podrían anticipar antes. Deje que el JIT haga su trabajo 🙂

String.Empty es un campo de solo lectura , mientras que "" es una const . Esto significa que no puede usar String.Empty en una sentencia switch porque no es una constante.

Otra diferencia es que String.Empty genera un código CIL más grande. Mientras que el código para hacer referencia a “” y String.Empty tiene la misma longitud, el comstackdor no optimiza la concatenación de cadenas (ver la publicación de blog de Eric Lippert) para los argumentos de String.Empty. Las siguientes funciones equivalentes

 string foo() { return "foo" + ""; } string bar() { return "bar" + string.Empty; } 

generar esto IL

 .method private hidebysig instance string foo() cil managed { .maxstack 8 L_0000: ldstr "foo" L_0005: ret } .method private hidebysig instance string bar() cil managed { .maxstack 8 L_0000: ldstr "bar" L_0005: ldsfld string [mscorlib]System.String::Empty L_000a: call string [mscorlib]System.String::Concat(string, string) L_000f: ret } 

Las respuestas anteriores son técnicamente correctas, pero lo que realmente puede querer usar para obtener la mejor legibilidad del código y la menor posibilidad de una excepción es String.IsNullOrEmpty (s)

Use String.Empty lugar de "" .

Esto es más por la velocidad que por el uso de la memoria, pero es un consejo útil. El "" es un literal así que actuará como un literal: en el primer uso se crea y para los siguientes usos se devuelve su referencia. ¡Solo una instancia de "" se almacenará en la memoria sin importar cuántas veces la usemos! No veo ninguna penalización de memoria aquí. El problema es que cada vez que se usa "" , se ejecuta un ciclo de comparación para verificar si "" ya está en el grupo interno. Por otro lado, String.Empty es una referencia a un "" almacenado en la zona de memoria de .NET Framework . String.Empty apunta a la misma dirección de memoria para las aplicaciones VB.NET y C #. Entonces, ¿por qué buscar una referencia cada vez que necesita "" cuando tiene esa referencia en String.Empty ?

Referencia: String.Empty vs ""

String.Empty no crea un objeto mientras que “” lo hace. La diferencia, como se señala aquí , es trivial, sin embargo.

Todas las instancias de “” son el mismo literal de cadena interna (o deberían serlo). Por lo tanto, realmente no lanzará un objeto nuevo en el montón cada vez que use “”, sino que solo creará una referencia al mismo objeto interno. Habiendo dicho eso, prefiero el hilo. Vacío. Creo que hace que el código sea más legible.

String.Empty a usar String.Empty lugar de "" por una razón simple, aunque no obvia: "" y "" NO son lo mismo, el primero realmente tiene 16 caracteres de ancho cero. Obviamente ningún desarrollador competente va a poner caracteres de ancho cero en su código, pero si entran allí, puede ser una pesadilla de mantenimiento.

Notas:

  • Usé U + FEFF en este ejemplo.

  • No estoy seguro de si SO se va a comer esos personajes, pero pruébelo usted mismo con uno de los muchos caracteres de ancho cero

  • Solo encontré esto gracias a https://codegolf.stackexchange.com/

 string mystring = ""; ldstr "" 

ldstr empuja una nueva referencia de objeto a un literal de cadena almacenado en los metadatos.

 string mystring = String.Empty; ldsfld string [mscorlib]System.String::Empty 

ldsfld empuja el valor de un campo estático en la stack de evaluación

String.Empty a usar String.Empty lugar de "" porque en mi humilde opinión es más claro y menos VB-ish.

En este aspecto desde el punto de vista de Entity Framework: EF versiones 6.1.3 parece tratar String.Empty y “” de manera diferente al validar.

string.Empty se trata como un valor nulo para propósitos de validación y generará un error de validación si se usa en un campo Requerido (atribuido); donde como “” pasará la validación y no arrojará el error.

Este problema se puede resolver en EF 7+. Referencia: – https://github.com/aspnet/EntityFramework/issues/2610 ).

Editar: [Obligatorio (AllowEmptyStrings = true)] resolverá este problema, permitiendo que string.Empty valide.

Como String.Empty no es una constante de tiempo de comstackción, no puede usarlo como valor predeterminado en la definición de la función.

 public void test(int i=0,string s="") { // Function Body } 

Todos aquí dieron una buena aclaración teórica. Tenía una duda similar. Así que probé una encoding básica sobre eso. Y encontré la diferencia. Aquí está la diferencia.

 string str=null; Console.WriteLine(str.Length); // Exception(NullRefernceException) for pointing to null reference. string str = string.Empty; Console.WriteLine(str.Length); // 0 

Por lo tanto, parece que “nulo” significa absolutamente nulo y “String.Empty” significa que contiene algún tipo de valor, pero está vacío.