En .Net, ¿por qué String.Empty es de solo lectura en lugar de una constante? Me pregunto si alguien sabe cuál fue el razonamiento detrás de esa decisión.
En .Net, ¿por qué String.Empty es de solo lectura en lugar de una constante? Me pregunto si alguien sabe cuál fue el razonamiento detrás de esa decisión.
Respuestas:
La razón que static readonly
se usa en lugar de const
se debe al uso con código no administrado, como lo indica Microsoft aquí en la versión Shared Source Common Language Infrastructure 2.0 . El archivo a mirar es sscli20\clr\src\bcl\system\string.cs
.
La constante vacía contiene el valor de cadena vacía. Necesitamos llamar al constructor de cadenas 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 nativo.
Encontré esta información de este útil artículo en CodeProject .
String.Empty
más solo por esa razón.
Creo que hay mucha confusión y malas respuestas aquí.
En primer lugar, los const
campos son static
miembros ( no miembros de instancia ).
Consulte 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 los public const
miembros son estáticos, uno no podría 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 de solo lectura es diferente de la palabra clave const. Un campo constante solo puede inicializarse 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 valores diferentes según el constructor utilizado. Además, si bien un campo constante 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.
const string
y static readonly string
hago lo mismo. Los valores constantes se sustituyen en el código vinculado, mientras que los valores de solo lectura estática están referenciados. Si tiene una const
biblioteca A que utiliza la biblioteca B, la biblioteca B reemplazará todas las referencias a esa const
variable con su valor literal; si esa variable fuera en su static readonly
lugar, sería referenciada y su valor determinado en tiempo de ejecución.
String.Empty read only instead of a constant?
Si hace que una cadena sea constante , el compilador se reemplaza con la cadena real en todas partes donde la llame y completa su código con la misma cadena por todas partes y cuando se ejecuta el código también es necesario leer una y otra vez esa cadena de la memoria diferente datos.
Si deja su cadena de lectura solo en un lugar como es 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 utilizando String.Empty como constante y, por cualquier motivo, el cambio de String.Empty, el dll compilado ya no funcionará de la misma manera, ya que crea cost
el código interno para mantener una copia de la 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 convocatoria de la 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 tipográfico corregido
Esta respuesta existe para fines históricos.
Originalmente:
Porque String
es una clase y por lo tanto no puede ser una constante.
Discusión extendida:
Una gran cantidad de diálogos útiles fueron elaborados al examinar esta respuesta, y en lugar de eliminarla, este contenido se reproduce directamente:
En .NET, (a diferencia de Java) string y String son exactamente lo mismo. Y sí, puede tener constantes literales de cadena en .NET - DrJokepu 03 de febrero de 2009 a las 16:57
¿Estás diciendo que una clase no puede tener constantes? - StingyJack 03 de febrero de 2009 a las 16:58
Sí, los objetos tienen que usar solo lectura. Solo las estructuras pueden hacer constantes. Creo que cuando usa en
string
lugar delString
compilador, cambia la constante en un solo lectura para usted. 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" fue un poco demasiado libre de contexto;) - Leonidas 03 de febrero de 2009 a las 17:01
string.Empty es una 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 03 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. ¡Se requiere investigación esta noche! - Garry Shutler 3 de febrero de 2009 a las 17:07
La cadena vacía es una instancia de la clase de cadena. Vacío es un campo estático (no es una propiedad, estoy corregido) en la clase String. Básicamente, la diferencia entre un puntero y lo que señala. Si no fuera de solo lectura, podríamos cambiar a qué instancia se refiere el campo Vacío. - tvanfosson 03 de febrero de 2009 a las 17:07
Garry, no necesitas hacer ninguna investigación. Piénsalo. La cadena es una clase. Vacío es una instancia de una cadena. - senfo 3 de febrero de 2009 a las 17:12
Hay algo que no entiendo: ¿cómo puede el constructor estático de la clase String crear una instancia de la clase String? ¿No es una especie de escenario de "la gallina o el huevo"? - DrJokepu 03 de febrero de 2009 a las 17:12 5
Esta respuesta sería correcta para casi cualquier otra clase que no sea System.String. .NET realiza una gran cantidad de funciones especiales para cadenas, y una de ellas es que PUEDES tener constantes de cadena, solo pruébalo. En este caso, Jeff Yates tiene la respuesta correcta. - Joel Mueller 03 de febrero de 2009 a las 19:25
Como se describe en §7.18, una expresión constante es una expresión que puede evaluarse completamente en tiempo de compilación. Dado que la única forma de crear un valor no nulo de un tipo de referencia que no sea 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 constantes de tipos de referencia que no sea string 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