¿Cuál es la diferencia entre una cadena mutable e inmutable en C #?
¿Cuál es la diferencia entre una cadena mutable e inmutable en C #?
Respuestas:
Mutable e inmutable son palabras inglesas que significan "puede cambiar" y "no puede cambiar" respectivamente. El significado de las palabras es el mismo en el contexto de TI; es decir
El significado de estas palabras es el mismo en C # / .NET que en otros lenguajes / entornos de programación, aunque (obviamente) los nombres de los tipos pueden diferir, al igual que otros detalles.
Para el registro:
String
es el tipo de cadena inmutable estándar C # / .Net StringBuilder
es el tipo de cadena mutable estándar C # / .Net Para "efectuar un cambio" en una cadena representada como C # String
, en realidad crea un nuevo String
objeto. El original String
no se cambia ... porque no se puede cambiar.
En la mayoría de los casos es mejor usarlo String
porque es una razón más fácil sobre ellos; por ejemplo, no necesita considerar la posibilidad de que algún otro hilo pueda "cambiar mi cadena". Sin embargo, cuando necesita construir o modificar una cadena usando una secuencia de operaciones, puede ser más eficiente usar a StringBuilder
.
Y finalmente, para aquellas personas que afirman que a StringBuilder
no es una cadena porque no es inmutable, la documentación de Microsoft describe StringBuilder
lo siguiente:
"Representa una cadena mutable de caracteres. Esta clase no se puede heredar".
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 alterar una cadena muchas veces, como múltiples concatenaciones, úsela StringBuilder
.
O(N^2)
comportamiento ...
Un objeto es mutable si, una vez creado, su estado puede cambiarse llamando a varias operaciones en él, de lo contrario es inmutable.
En C # (y .NET) una cadena está representada por la clase System.String. La string
palabra clave es un alias para esta clase.
La clase System.String es inmutable, es decir, una vez creada, su estado no puede modificarse .
Así que todas las operaciones que realice en una cadena como Substring
, Remove
, Replace
, concatenación usando el operador '+', etc va a crear una nueva cadena y lo devuelve.
Vea el siguiente programa para demostración:
string str = "mystring";
string newString = str.Substring(2);
Console.WriteLine(newString);
Console.WriteLine(str);
Esto imprimirá 'string' y 'mystring' respectivamente.
Para obtener los beneficios de la inmutabilidad y por qué las cadenas son inmutables, compruebe ¿Por qué .NET String es inmutable? .
Si desea tener una cadena que desea modificar a menudo, puede usar la StringBuilder
clase. Las operaciones en una StringBuilder
instancia modificarán el mismo objeto .
Para obtener más consejos sobre cuándo usar, StringBuilder
consulte ¿ Cuándo usar StringBuilder? .
Todos los string
objetos son inmutables en C #. Los objetos de la clase string
, una vez creados, nunca pueden representar ningún valor que no sea con el que fueron construidos. Todas las operaciones que parecen "cambiar" una cadena en su lugar producen una nueva. Esto es ineficiente con la memoria, pero extremadamente útil con respecto a poder confiar en que una cadena no cambiará de forma debajo de usted, porque 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 pueden modificarse. 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 tiene un objeto mutable, el más similar a String es StringBuffer
, entonces debe hacer una copia del mismo si desea estar absolutamente seguro de que no cambiará debajo de usted. Esta es la razón por la cual los objetos mutables son peligrosos para usar como claves en cualquier forma Dictionary
o conjunto: los objetos en sí mismos podrían cambiar, y la estructura de datos no tendría forma de saberlo, lo que llevaría a datos corruptos que eventualmente colapsarían su programa.
Sin embargo, puede cambiar su contenido, por lo que es mucho, mucho más eficiente en memoria que hacer una copia completa porque quería cambiar un solo carácter, o algo similar.
En general, lo correcto es usar objetos mutables mientras está creando algo, y objetos inmutables una vez que haya terminado. Esto se aplica a los 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 corromper su datos.
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 en sí no modifica ningún objeto nuevo creado como en el caso de StringBuilder
En .NET System.String (también conocido como string) es un objeto inmutable. Eso significa que cuando creas un objeto no puedes cambiar su valor después. Solo puede 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 investiga el código. Verá que cada vez que cambia un objeto de System.String, en realidad está creando uno nuevo. Pero en System.Text.StringBuilder cada vez que cambia el valor del texto no recrea 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
Las cadenas son mutables porque .NET usa un grupo de cadenas detrás de la escena. Significa :
string name = "My Country";
string name2 = "My Country";
Tanto name como name2 se refieren a la misma ubicación de memoria del conjunto de cadenas. Ahora suponga que desea cambiar el nombre2 a:
name2 = "My Loving Country";
Buscará en el grupo de cadenas la cadena "My Loving Country". Si lo encuentra, obtendrá la referencia del mismo. Se creará otra cadena nueva y sabia "My Loving Country" en el grupo de cadenas y name2 obtendrá la referencia. Pero todo este proceso " Mi país " no cambió porque otra variable como el nombre todavía lo está usando. Y esa es la razón por la cual las cadenas son INMUTABLES .
StringBuilder funciona de manera diferente y no utiliza un conjunto de cadenas. Cuando creamos cualquier instancia de StringBuilder:
var address = new StringBuilder(500);
Asigna un fragmento de memoria de 500 bytes 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 sea de ayuda.
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 llama a Concat, Substring, etc. y usan aritmética de puntero para copiar a la nueva cadena. Las cadenas simplemente no se mutan, de ahí que se las considere "inmutables".
Por cierto, no intente esto con literales de cadena o dañará gravemente 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 .NET Framework de escritorio; en otras palabras, bar
y baz
señalar exactamente la misma cadena, por lo que mutar una mutará a la otra. Sin embargo, todo esto está muy bien si estás usando una plataforma no administrada como WinRT, que carece de internados de cadenas.
Para aclarar, no existe una cadena mutable en C # (o .NET en general). Otras langues admiten cadenas mutables (cadenas que pueden cambiar) pero el marco .NET no.
Entonces, la respuesta correcta a su pregunta es TODAS las cadenas son inmutables en C #.
cadena tiene un significado específico. La palabra clave "string" en minúsculas es simplemente un acceso directo para un objeto instanciado de la clase System.String. Todos los objetos creados a partir de la clase de cadena SIEMPRE son inmutables.
Si desea una representación de texto mutable, debe usar otra clase como StringBuilder. StringBuilder le permite construir iterativamente una colección de 'palabras' y luego convertirla en una cadena (una vez más inmutable).
StringBuilder
contradice esto: ver msdn.microsoft.com/en-us/library/…
El valor de los datos no puede modificarse. Nota: El valor de la variable puede modificarse, pero el valor de datos inmutable original se descartó y se creó un nuevo valor de datos en la memoria.
De http://yassershaikh.com/what-is-the-difference-between-strings-and-stringbuilder-in-c-net/
Respuesta corta: String es inmutable, mientras que StringBuilder es mutable.
Qué significa eso ? Wiki dice: En la orientación a objetos, un objeto inmutable es un objeto cuyo estado no puede modificarse después de su creación. Esto contrasta con un objeto mutable, que se puede modificar después de crearlo.
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, que requiere una nueva asignación de espacio para ese nuevo objeto.
En situaciones donde necesita realizar modificaciones repetidas a una cadena, la sobrecarga asociada con la creación de un nuevo objeto de cadena puede ser costosa.
La clase System.Text.StringBuilder se puede usar cuando desea 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.
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();
La cadena en C # es inmutable. Si lo concatena con cualquier cadena, en realidad está creando una nueva cadena, ¡ese es un nuevo objeto de cadena! Pero StringBuilder crea una cadena mutable.
StringBuilder es una mejor opción para concatenar una cadena de datos enorme porque StringBuilder es un tipo de cadena mutable y el objeto StringBuilder es un tipo inmutable, lo que significa que StringBuilder nunca crea una nueva instancia de objeto mientras concatena la cadena.
Si estamos usando una cadena en lugar de StringBuilder para lograr la concatenación, creará una nueva instancia en la memoria cada vez.