Pregunta

Me temo que es una pregunta muy tonta, pero algo me debe faltar.

¿Por qué uno podría querer usar Cadena.Copiar(cadena)?

La documentación dice el método.

Crea una nueva instancia de cadena con el mismo valor que una cadena especificada.

Dado que las cadenas son inmutables en .NET, no estoy seguro de cuál es el beneficio de usar este método, ya que creo que

 string copy = String.Copy(otherString);

para todos los efectos prácticos parecería producir el mismo resultado que

 string copy = otherString;

Es decir, excepto por cualquier contabilidad interna que se esté llevando a cabo y el hecho de que la copia no sea ReferenceEquals para otherString, no hay diferencias observables: String es una clase inmutable cuya igualdad se basa en el valor, no en la identidad.(Gracias a @Andrew Hare por señalar que mi redacción original no era lo suficientemente precisa como para indicar que me di cuenta de que había una diferencia entre Copying y no, pero estaba preocupado por la falta percibida de útil diferencia.)

Por supuesto, cuando pasó un null argumento, Copiar arroja un ArgumentNullException, y la "nueva instancia" podría consumir más memoria.Esto último no parece ser un beneficio, y no estoy seguro de que la verificación nula sea una ventaja lo suficientemente grande como para justificar un método de copia completo.

Gracias.

¿Fue útil?

Solución

Con String.Copy se están asignando realidad nueva memoria y copiar los caracteres de una cadena a otra; se obtiene una completamente nueva instancia en lugar de tener dos variables que son la misma instancia. Esto puede importar si se utiliza la cadena con código no administrado que se ocupa de las posiciones de memoria directamente y puede mutar la cadena.

Otros consejos

String.Copy devuelve un nuevo String y no da los mismos resultados que

String copy = otherString;

Prueba esto:

using System;

class Program
{
    static void Main()
    {
        String test = "test";
        String test2 = test;
        String test3 = String.Copy(test);

        Console.WriteLine(Object.ReferenceEquals(test, test2));
        Console.WriteLine(Object.ReferenceEquals(test, test3));

        Console.ReadLine();
    }
}

cuando estableces test2 = test estas referencias apuntan a lo mismo String.El Copy La función devuelve un nuevo String referencia que tiene el mismo contenido pero como un objeto diferente en el montón.


Editar: Hay mucha gente que está bastante molesta porque no respondí la pregunta del OP.Creo que respondí la pregunta corrigiendo una premisa incorrecta en la pregunta misma.Aquí hay una pregunta y una respuesta análogas (si no demasiado simplificadas) que espero ilustren mi punto:

Pregunta:

He observado que mi auto tiene dos puertas, una a cada lado del auto.Creo que es cierto que independientemente de la puerta que utilice, acabaré sentado en el asiento del conductor.¿Cuál es el propósito de la otra puerta?

Respuesta:

En realidad no es cierto que si utilizas cualquiera de las puertas acabarás en el asiento del conductor.Si usas la puerta del lado del conductor terminarás en el asiento del conductor y si usas la puerta del lado del pasajero terminarás en el asiento del pasajero.

Ahora bien, en este ejemplo se podría argumentar que la respuesta no es realmente una respuesta, ya que la pregunta era "¿cuál es el propósito de la puerta del lado del pasajero?".Pero dado que esa pregunta se basó totalmente en una idea errónea sobre cómo funcionaban las puertas, ¿no se sigue que la refutación de la premisa arrojará nueva luz sobre el propósito de la otra puerta por deducción?

Aquí hay una pieza del rompecabezas. No explica por qué desea hacerlo, pero sí ayuda a explicar una diferencia funcional.

Si el pin de la cadena usando el fixed palabra clave, el contenido sería mutable. De la parte superior de mi cabeza, no puedo pensar en una situación en la que usted quiere hacer esto, pero es posible.

string original = "Hello World";
string refCopy = original;
string deepCopy = String.Copy(original);

fixed(char* pStr = original)
{
   *pStr = 'J';
}

Console.WriteLine(original);
Console.WriteLine(refCopy);
Console.WriteLine(deepCopy);

Salida:

Jello World
Jello World
Hello World

Una búsqueda rápida a través de la BCL para .NET 4.0 muestra que el método se llama string.Copy en alrededor de una media docena de lugares. Los usos se dividen en aproximadamente estas categorías:

  1. Para interoperabilidad con funciones nativas que pueden dañar las cadenas pasadas a ellos. Si no puede afectar a la relación P / Invoke declaración y no se puede arreglar la función de ser llamado, <=> es la mejor opción.

  2. En situaciones en las que la cadena se modifica en el lugar por razones de rendimiento. Si usted necesita para convertir unos pocos caracteres en minúsculas en una potencialmente larga cadena, la única manera de hacerlo sin necesidad de copiar la cadena dos veces y la creación de basura adicional es que a mutar.

  3. En los lugares donde no parece necesario. Es muy posible que algunos programadores están más acostumbrados a las cadenas de Java o C ++ y no se dan cuenta de que la copia de una cadena en C # no suele ser útil.

string a = "abc";
string b = String.Copy(a);

Monitor.Enter(a); // not the same as Monitor.Enter(b);

Sin embargo

string c = "123";
string d = c;
Monitor.Enter(c); // the same as Monitor.Enter(d);

En cuanto a la forma en que a alguien le importará, creo que está ahí para que esté completo.


También

StringBuilder sb = new StringBuilder(100);
sb.Append("abc");
string a = sb.ToString();
string b = String.Copy(a);

Creo a ocupará más RAM entonces b, como a apunta al buffer de tamaño 100 que el StringBuilder creado.(Mira el interior del StringBuilder.ToString() método)


Creo StringBuilder hace uso de String.Copy() y ser parte del framework .NET StringBuildercambia el contenido del string.entonces un string no siempre es inmutable.

Además de lo dicho tvanfosson (no creo que se puede acceder a la memoria intermedia utilizada por una cadena gestionada desde el código no administrado ... Sé que sería difícil, por lo menos), creo que puede haber una diferencia si la cadena se utiliza como objeto de hacer un bloqueo en la funcionalidad multiproceso.

Por ejemplo ...

using System;

public class Class1
{
    string example1 = "example";
    string example2 = example1;

    public void ExampleMethod1()
    {
        lock (example1)
        {
            Console.WriteLine("Locked example 1");
            //do stuff...
        }
    }

    public void ExampleMethod2()
    {
        lock (example2)
        {
            Console.WriteLine("Locked example 2");
            //do stuff
        }
    }
}

Creo que si los dos métodos de ejemplo se ejecutan en paralelo, serán Bloqueo del mismo objeto y, por tanto no serán capaces de ejecutar mientras el otro está dentro de su bloque de cerradura.

Sin embargo, si lo cambia a esto ...

using System;

public class Class1
{
    string example1 = "example";
    string example2 = string.Copy(example1);

    public void ExampleMethod1()
    {
        lock (example1)
        {
            Console.WriteLine("Locked example 1");
            //do stuff...
        }
    }

    public void ExampleMethod2()
    {
        lock (example2)
        {
            Console.WriteLine("Locked example 2");
            //do stuff
        }
    }
}

A continuación, creo que sólo bloquear la ejecución de otros hilos de ejecución el mismo método (es decir, todos los hilos de ejecución ExampleMethod1 se bloqueará hasta que cada uno termina, pero que no interfieran con hilos de ejecución ExampleMethod2).

No estoy seguro es un utilidad diferencia, ya que hay mejores mecanismos para la sincronización (no creo que las cadenas de bloqueo es una muy buena idea).

string a = "test";
string b = a;
//Object.ReferenceEquals(a,b) is true
a += "more";
//Object.ReferenceEquals(a,b) is now false !

Detección automática de cambio?

No estoy seguro de cómo Cadena siendo implementado en .NET, pero creo que Java es una buena referencia.

En Java, nueva cadena (str) también hacer lo String.copy (str); no, asignar una nueva cadena con mismo valor.

Se parece inútil, pero es muy útil en la optimización de la memoria.

cadena contiene un char [] con desplazamiento y la longitud en la aplicación. Si lo hace un algo así como una subcadena, no va a hacer una copia de la memoria, sino devolver una nueva instancia de String compartiendo misma char []. En muchos casos, este patrón se ahorrará una gran cantidad de memoria y copia de la asignación. Sin embargo, si la subcadena una pequeña pieza dentro de una gran cadena larga. Todavía hará referencia a grande char [] incluso la cadena grande original es capaz de ser GC.

String longString = // read 1MB text from a text file
String memoryLeak = largeString.substring(100,102); 
largeString=null;
// memoryLeak will be sized 1MB in the memory
String smaller = new String(largeString.substring(100,102));
// smaller will be only few bytes in the memory

Se puede forzar al nuevo objeto String asignar su propio char [] para evitar fugas de memoria oculta / residuos.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top