son - ¿Cuál es la diferencia entre una cadena mutable e inmutable en C#?
objetos inmutables c# (14)
¿Cuál es la diferencia entre una cadena mutable e inmutable en C #?
Aquí está el ejemplo de cadena inmutable y generador de cadenas mutables
Console.WriteLine("Mutable String Builder");
Console.WriteLine("....................................");
Console.WriteLine();
StringBuilder sb = new StringBuilder("Very Good Morning");
Console.WriteLine(sb.ToString());
sb.Remove(0, 5);
Console.WriteLine(sb.ToString());
Console.WriteLine();
Console.WriteLine("Immutable String");
Console.WriteLine("....................................");
Console.WriteLine();
string s = "Very Good Morning";
Console.WriteLine(s);
s.Substring(0, 5);
Console.WriteLine(s);
Console.ReadLine();
De http://yassershaikh.com/what-is-the-difference-between-strings-and-stringbuilder-in-c-net/
Respuesta corta: la cadena es inmutable, mientras que StringBuilder es mutable.
Qué significa eso ? Wiki dice: En objetos orientados, un objeto inmutable es un objeto cuyo estado no puede modificarse después de haber sido creado. Esto está en contraste con un objeto mutable, que puede modificarse después de haber sido creado.
De la documentación de la clase StringBuilder:
El objeto String es inmutable. Cada vez que utiliza uno de los métodos en la clase System.String, crea un nuevo objeto de cadena en la memoria, lo que requiere una nueva asignación de espacio para ese nuevo objeto.
En situaciones donde necesita realizar modificaciones repetidas en una cadena, la sobrecarga asociada con la creación de un nuevo objeto String puede ser costosa.
La clase System.Text.StringBuilder se puede usar cuando desee modificar una cadena sin crear un nuevo objeto. Por ejemplo, usar la clase StringBuilder puede aumentar el rendimiento al concatenar muchas cadenas juntas en un bucle.
El valor de los datos no puede ser cambiado. Nota: El valor de la variable puede cambiarse, pero el valor de datos inmutables original se descartó y se creó un nuevo valor de datos en la memoria.
En .NET System.String (también conocido como cadena) es un objeto inmutable. Eso significa que cuando creas un objeto no puedes cambiar su valor después. Solo puedes recrear un objeto inmutable.
System.Text.StringBuilder es equivalente mutable de System.String y puede cambiar su valor
Por ejemplo:
class Program
{
static void Main(string[] args)
{
System.String str = "inital value";
str = "/nsecond value";
str = "/nthird value";
StringBuilder sb = new StringBuilder();
sb.Append("initial value");
sb.AppendLine("second value");
sb.AppendLine("third value");
}
}
Genera el siguiente MSIL: si investigas el código. Verás que cada vez que chaneas un objeto de System.String estás creando uno nuevo. Pero en System.Text.StringBuilder cada vez que cambie el valor del texto, no volverá a crear el objeto.
.method private hidebysig static void Main(string[] args) cil managed
{
.entrypoint
// Code size 62 (0x3e)
.maxstack 2
.locals init ([0] string str,
[1] class [mscorlib]System.Text.StringBuilder sb)
IL_0000: nop
IL_0001: ldstr "inital value"
IL_0006: stloc.0
IL_0007: ldstr "/nsecond value"
IL_000c: stloc.0
IL_000d: ldstr "/nthird value"
IL_0012: stloc.0
IL_0013: newobj instance void [mscorlib]System.Text.StringBuilder::.ctor()
IL_0018: stloc.1
IL_0019: ldloc.1
IL_001a: ldstr "initial value"
IL_001f: callvirt instance class [mscorlib]System.Text.StringBuilder [mscorlib]System.Text.StringBuilder::Append(string)
IL_0024: pop
IL_0025: ldloc.1
IL_0026: ldstr "second value"
IL_002b: callvirt instance class [mscorlib]System.Text.StringBuilder [mscorlib]System.Text.StringBuilder::AppendLine(string)
IL_0030: pop
IL_0031: ldloc.1
IL_0032: ldstr "third value"
IL_0037: callvirt instance class [mscorlib]System.Text.StringBuilder [mscorlib]System.Text.StringBuilder::AppendLine(string)
IL_003c: pop
IL_003d: ret
} // end of method Program::Main
Inmutable:
Cuando realiza alguna operación en un objeto, crea un nuevo objeto, por lo tanto, el estado no es modificable como en el caso de una cadena.
Mudable
Cuando realiza alguna operación en un objeto, el objeto mismo no modifica ningún nuevo objeto creado como en el caso de StringBuilder
La cadena en C # es inmutable. Si lo concatena con cualquier cadena, en realidad está creando una nueva cadena, ¡eso es un nuevo objeto de cadena! Pero StringBuilder crea una cadena mutable.
Las cadenas son mutables porque .NET utiliza un grupo de cadenas detrás de la escena. Significa :
string name = "My Country";
string name2 = "My Country";
Tanto el nombre como el nombre2 hacen referencia a la misma ubicación de memoria del conjunto de cadenas. Ahora supongamos que quiere cambiar name2 por:
name2 = "My Loving Country";
Buscará en el grupo de cadenas para la cadena "My Loving Country", si se encuentra, obtendrá la referencia de otra cadena sabia nueva "My Loving Country" se creará en el conjunto de cadenas y name2 obtendrá una referencia de ello. Pero todo este proceso " Mi país " no se modificó porque otras variables como el nombre todavía lo están usando. Y esa es la razón por la cual la cadena es INMUTABLE .
StringBuilder funciona de manera diferente y no utiliza grupo de cadenas. Cuando creamos cualquier instancia de StringBuilder:
var address = new StringBuilder(500);
Se asigna trozo de memoria de 500 bytes de tamaño para esta instancia y todas las operaciones solo modifican esta ubicación de memoria y esta memoria no se comparte con ningún otro objeto. Y esa es la razón por la cual StringBuilder es MUTABLE .
Espero que ayude
Mutable e inmutable son palabras en inglés que significan "pueden cambiar" y "no pueden cambiar" respectivamente. El significado de las palabras es el mismo en el contexto de TI; es decir
- una cadena mutable se puede cambiar, y
- una cuerda inmutable no puede ser cambiada.
Los significados de estas palabras son los mismos en C # / .NET que en otros lenguajes / lenguajes de programación, aunque (obviamente) los nombres de los tipos pueden diferir, al igual que otros detalles.
Para el registro:
-
String
es el tipo estándar de cadena inmóvil C # / .Net -
StringBuilder
es el tipo de cadena mutable C # / .Net estándar
Para "efectuar un cambio" en una cadena representada como una String
C #, realmente creas un nuevo objeto String
. La String
original no ha cambiado ... porque es inmutable.
En la mayoría de los casos, es mejor usar String
porque es más fácil razonar sobre ellos; por ejemplo, no es necesario considerar la posibilidad de que algún otro hilo pueda "cambiar mi cadena". Sin embargo, cuando necesite construir o modificar una cadena usando una secuencia de operaciones, puede ser más eficiente usar un StringBuilder
.
Ninguno, en realidad. La clase String es mutable.
unsafe
{
string foo = string.Copy("I am immutable.");
fixed (char* pChar = foo)
{
char* pFoo = pChar;
pFoo[5] = '' '';
pFoo[6] = '' '';
}
Console.WriteLine(foo); // "I am mutable."
}
Este tipo de lógica se realiza todo el tiempo en las clases String y StringBuilder, en realidad. Simplemente asignan una nueva cadena cada vez que llamas a Concat, Substring, etc. y usan la aritmética del puntero para copiar a la nueva cadena. Las cadenas simplemente no se mutan a sí mismas, de ahí que se las considere "inmutables".
Por cierto, no intente esto con cadenas literales o arruinará su programa:
string bar = "I am a string.";
fixed (char* pChar = bar)
{
char* pBar = pChar;
pBar[2] = '' '';
}
string baz = "I am a string.";
Console.WriteLine(baz); // "I m a string."
Esto se debe a que los literales de cadena están internados en el escritorio .NET Framework; en otras palabras, bar
y baz
apuntan a la misma cadena exacta, por lo que mutar uno mutará el otro. Aunque todo esto está bien y muy bien si estás usando una plataforma no administrada como WinRT, que carece de intercepción de cadenas.
Para aclarar, no existe una cadena mutable en C # (o .NET en general). Otros langues soportan cadenas mutables (cadena que puede cambiar) pero el framework .NET no.
Entonces, la respuesta correcta a su pregunta es que TODAS las cadenas son inmutables en C #.
cadena tiene un significado específico. La palabra clave minúscula "cadena" es simplemente un acceso directo para un objeto instanciado de la clase System.String. Todos los objetos creados a partir de la clase de cuerda son SIEMPRE inmutables.
Si desea una representación mutable de texto, entonces necesita usar otra clase como StringBuilder. StringBuilder te permite construir iterativamente una colección de ''palabras'' y luego convertirla en una cadena (una vez más inmutable).
Todos string
objetos de string
son inmutables en C #. Los objetos de la string
clase, una vez creados, nunca pueden representar ningún valor que no sea con el que se construyeron. Todas las operaciones que parecen "cambiar" una cadena producen una nueva. Esto es ineficiente con la memoria, pero extremadamente útil para poder confiar en que una cadena no cambiará de forma debajo de usted, ya que mientras no cambie su referencia, la cadena a la que se hace referencia nunca cambiará.
Un objeto mutable, por el contrario, tiene campos de datos que se pueden modificar. Uno o más de sus métodos cambiarán el contenido del objeto, o tiene una propiedad que, cuando se escribe, cambiará el valor del objeto.
Si tienes un objeto mutable, el más similar a String es StringBuffer
, entonces debes hacer una copia si quieres estar absolutamente seguro de que no cambiará debajo de ti. Esta es la razón por la cual los objetos mutables son peligrosos de usar como claves en cualquier forma de Dictionary
o conjunto: los objetos mismos podrían cambiar, y la estructura de datos no tendría forma de saberlo, lo que llevaría a datos corruptos que, eventualmente, bloquearían su programa.
Sin embargo, puede cambiar su contenido, por lo que es mucho, mucho más eficiente en la memoria que hacer una copia completa porque quería cambiar un solo carácter o algo similar.
Generalmente, lo correcto es usar objetos mutables mientras crea algo y objetos inmutables una vez que haya terminado. Esto se aplica a objetos que tienen formas inmutables, por supuesto; la mayoría de las colecciones no. Sin embargo, a menudo es útil proporcionar formas de colecciones de solo lectura, que es el equivalente de inmutable, al enviar el estado interno de su colección a otros contextos; de lo contrario, algo podría tomar ese valor de retorno, hacerle algo y dañar su datos.
Un objeto es mutable si, una vez creado, su estado se puede cambiar llamando varias operaciones en él, de lo contrario es inmutable.
Cadena inmutable
En C # (y .NET) una cadena está representada por la clase System.String. La palabra clave string
es un alias para esta clase.
La clase System.String es inmutable, es decir, una vez creada, su estado no puede modificarse .
De modo que todas las operaciones que realice en una cadena como Subcadena, Eliminar, Reemplazar, concatenación usando el operador ''+'', etc. crearán una nueva cadena y la devolverán.
Vea el siguiente programa para demostración -
string str = "mystring";
string newString = str.Substring(3);
Console.WriteLine(newString);
Console.WriteLine(str);
Esto imprimirá ''cadena'' y ''mystring'' respectivamente.
Para conocer los beneficios de la inmutabilidad y por qué las cadenas son inmutables, compruebe por qué .NET String es inmutable. .
Cadena mutable
Si desea tener una cadena que quiera modificar a menudo, puede usar la clase StringBuilder
. Las operaciones en una instancia de StringBuilder
modificarán el mismo objeto .
Para obtener más consejos sobre cuándo usar StringBuilder
consulte ¿ Cuándo usar StringBuilder? .
en detalle de implementación.
CLR2''s System.String es muttable. StringBuilder.Append llamando a String.AppendInplace (método privado)
El System.String de CLR4 es imutable. StringBuilder tiene una matriz Char con fragmentación.
String
es inmutable
es decir, las cadenas no pueden ser alteradas. Cuando modifica una cadena (al agregarla, por ejemplo), en realidad está creando una nueva cadena.
Pero StringBuilder
no es inmutable (más bien, es mutable)
así que si tiene que modificar una cadena muchas veces, como múltiples concatenaciones, entonces use StringBuilder
.