.net - initialize - ¿Por qué no String.Empty es una constante?
char empty c# (4)
En .Net, ¿por qué String.Empty solo lee en lugar de una constante? Me pregunto si alguien sabe cuál fue el razonamiento detrás de esa decisión.
Creo que hay mucha confusión y malas respuestas aquí.
En primer lugar, los campos const
son miembros static
( no miembros de instancias ).
Verifique la sección 10.4 Constantes de la especificación del lenguaje C #.
Aunque las constantes se consideran miembros estáticos, una declaración constante no requiere ni permite un modificador estático.
Si public const
miembros de public const
son estáticos, no se puede considerar que una constante creará un nuevo objeto.
Dado esto, las siguientes líneas de código hacen exactamente lo mismo con respecto a la creación de un nuevo Objeto.
public static readonly string Empty = "";
public const string Empty = "";
Aquí hay una nota de Microsoft que explica la diferencia entre los 2:
La palabra clave readonly es diferente de la palabra clave const. Un campo const solo se puede inicializar en la declaración del campo. Un campo de solo lectura se puede inicializar en la declaración o en un constructor. Por lo tanto, los campos de solo lectura pueden tener diferentes valores según el constructor utilizado. Además, aunque un campo const es una constante de tiempo de compilación, el campo de solo lectura se puede usar para constantes de tiempo de ejecución, ...
Entonces encuentro que la única respuesta plausible aquí es la de Jeff Yates.
Esta respuesta existe para propósitos históricos.
Originalmente:
Porque String
es una clase y, por lo tanto, no puede ser una constante.
Discusión extendida:
Se desarrolló un gran diálogo útil para investigar esta respuesta, y en lugar de eliminarla, este contenido se reproduce directamente:
En .NET, (a diferencia de Java) string y String son exactamente iguales. Y sí, puede tener constantes literales de cadena en .NET - DrJokepu Feb 3 ''09 a las 16:57
¿Estás diciendo que una clase no puede tener constantes? - StingyJack 3 de febrero de 2009 a las 16:58
Sí, los objetos tienen que usar de solo lectura. Solo las estructuras pueden hacer constantes. Creo que cuando usas
string
lugar deString
el compilador cambia el const a readonly para ti. Todo tiene que ver con mantener contentos a los programadores de C. - Garry Shutler el 3 de febrero de 2009 a las 16:59tvanfosson acaba de explicarlo un poco más detallado. "X no puede ser una constante, porque el Y que contiene es una clase" era un poco demasiado libre de contexto;) - Leonidas Feb 3 ''09 a las 17:01
string.Empty es propiedad estática que devuelve una instancia de la clase String, es decir, la cadena vacía, no la clase de cadena en sí. - tvanfosson 3 de febrero de 2009 a las 17:01
Empty es una instancia de solo lectura (no es una propiedad) de la clase String. - Senfo 3 de febrero de 2009 a las 17:02
Herida en la cabeza. Sigo pensando que tengo razón, pero ahora estoy menos seguro. ¡Investigación requerida esta noche! - Garry Shutler el 3 de febrero de 2009 a las 17:07
La cadena vacía es una instancia de la clase de cadena. Empty es un campo estático (no una propiedad, me corresponde corregir) en la clase String. Básicamente la diferencia entre un puntero y aquello a lo que apunta. Si no fuera de solo lectura, podríamos cambiar a qué instancia se refiere el campo Vacío. - tvanfosson 3 de febrero de 2009 a las 17:07
Garry, no necesitas investigar. Piénsalo. String es una clase. Empty es una instancia de String. - Senfo 3 de febrero de 2009 a las 17:12
Hay algo que no entiendo muy bien: ¿cómo diablos puede el constructor estático de la clase String crear una instancia de la clase String? ¿No es algún tipo de escenario de "gallina o huevo"? - DrJokepu 3 de febrero de 2009 a las 17:12 5
Esta respuesta sería correcta para casi cualquier otra clase, excepto System.String. .NET realiza una gran cantidad de rendimiento especial para cuerdas, y una de ellas es que PUEDE tener constantes de cadena, solo inténtelo. En este caso, Jeff Yates tiene la respuesta correcta. - Joel Mueller 3 de febrero de 2009 a las 19:25
Como se describe en §7.18, una expresión constante es una expresión que se puede evaluar completamente en tiempo de compilación. Dado que la única forma de crear un valor no nulo de un tipo de referencia distinto de una cadena es aplicar el nuevo operador, y dado que el nuevo operador no está permitido en una expresión constante, el único valor posible para las constantes de los tipos de referencia que no sea una cadena es nulo. Los dos comentarios anteriores fueron tomados directamente de la especificación del lenguaje C # y reiteran lo que mencionó Joel Mueller. - senfo 4 de febrero de 2009 a las 15:05 5
La razón por la que se utiliza el static readonly
lugar de const
se debe usar con código no administrado, como lo indica Microsoft aquí en la Versión de Common Language Infrastructure 2.0 de Shared Source Language . El archivo para mirar es sscli20/clr/src/bcl/system/string.cs
.
La constante vacía contiene el valor de cadena vacía. Necesitamos llamar al constructor String para que el compilador no marque esto como un literal.
Marcar esto como literal significaría que no aparece como un campo al que podemos acceder desde el nativo.
Encontré esta información de este útil artículo en CodeProject .
String.Empty read only instead of a constant?
Si haces una cadena constante , entonces el compilador se reemplaza con la cadena real en cualquier lugar que lo llames y llenas tu código con la misma cadena y cuando el código se ejecuta también es necesario leer una y otra vez esa cadena de la memoria diferente datos.
Si deja la secuencia de lectura solo en un lugar, ya que es el String.Empty
, el programa mantiene la misma cadena solo en un lugar y la lee, o se refiere a ella, manteniendo los datos en la memoria como mínimo.
Además, si compila cualquier dll usando String.Empty como const, y por algún motivo el cambio String.Empty, entonces el dll compilado ya no funcionará, ya que el cost
hace que el código interno guarde una copia del archivo. cadena en cada llamada.
Vea este código por ejemplo:
public class OneName
{
const string cConst = "constant string";
static string cStatic = "static string";
readonly string cReadOnly = "read only string";
protected void Fun()
{
string cAddThemAll ;
cAddThemAll = cConst;
cAddThemAll = cStatic ;
cAddThemAll = cReadOnly;
}
}
vendrá por el compilador como:
public class OneName
{
// note that the const exist also here !
private const string cConst = "constant string";
private readonly string cReadOnly;
private static string cStatic;
static OneName()
{
cStatic = "static string";
}
public OneName()
{
this.cReadOnly = "read only string";
}
protected void Fun()
{
string cAddThemAll ;
// look here, will replace the const string everywhere is finds it.
cAddThemAll = "constant string";
cAddThemAll = cStatic;
// but the read only will only get it from "one place".
cAddThemAll = this.cReadOnly;
}
}
y la llamada de asamblea
cAddThemAll = cConst;
0000003e mov eax,dword ptr ds:[09379C0Ch]
00000044 mov dword ptr [ebp-44h],eax
cAddThemAll = cStatic ;
00000047 mov eax,dword ptr ds:[094E8C44h]
0000004c mov dword ptr [ebp-44h],eax
cAddThemAll = cReadOnly;
0000004f mov eax,dword ptr [ebp-3Ch]
00000052 mov eax,dword ptr [eax+0000017Ch]
00000058 mov dword ptr [ebp-44h],eax
Editar: error ortográfico corregido