Pergunta

Eu tenho medo que esta é uma pergunta muito boba, mas eu devo estar faltando alguma coisa.

Por que um quer usar String.Copy (string) ?

A documentação diz que o método

Cria uma nova instância da corda com o mesmo valor como uma String especificado.

Uma vez que strings são imutáveis ??em .NET, eu não tenho certeza qual é a vantagem de usar este método, como eu acho que

 string copy = String.Copy(otherString);

faria para todos os efeitos práticos parecem produzir o mesmo resultado que

 string copy = otherString;

Isto é, exceto por qualquer contabilidade que está acontecendo, eo fato de que a cópia não é ReferenceEquals para otherString interna, não há diferenças observáveis ??- corda sendo uma classe imutável cuja igualdade é baseado no valor, não a identidade. (Graças a @ Andrew Hare por apontar que a minha formulação original não foi suficiente precisa para indicar que eu percebi que havia uma diferença entre Copying e não, mas estava preocupado com a percepção de falta de útil diferença.)

É claro que quando passado um argumento null, Copy lança uma ArgumentNullException, ea "nova instância" pode consumir mais memória. Este último não parece ser um benefício, e não tenho certeza que o cheque nulo é um bônus grande o suficiente para justificar um método de copiar todo.

Graças.

Foi útil?

Solução

Com String.Copy você está realmente alocar nova memória e copiar os caracteres de uma cadeia para outra; você começa uma nova instância em oposição a ter ambas as variáveis, sendo a mesma instância. Isso pode importa se você usar a corda com código não gerenciado que lida com os locais de memória diretamente e podem sofrer mutações a string.

Outras dicas

String.Copy retorna uma nova String e não produz os mesmos resultados que

String copy = otherString;

Tente isto:

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();
    }
}

Quando você define test2 = test estas referências apontam para o mesmo String. A função Copy retorna uma nova referência String que tem as mesmas conteúdo , mas como um objeto diferente na pilha.


Editar: Há um monte de pessoas que são muito chateado que eu não responder à pergunta do OP. Eu acredito que eu fiz responder à pergunta, corrigindo uma premissa errada na própria pergunta. Aqui é um análogo (se não simplista) de perguntas e respostas que esperamos ilustrar meu ponto:

Pergunta:

Eu observei que meu carro tem duas portas, uma de cada lado do carro. Eu acredito que seja verdade que, independentemente de qual porta eu uso I vai acabar sentado no banco do motorista. Qual é o objetivo da outra porta?

Resposta:

Na verdade, não é verdade que se você usar qualquer porta que você vai acabar no banco do motorista. Se você usar a porta do lado do motorista, você vai acabar no banco do motorista e se você usar a porta do lado do passageiro, você vai acabar no banco do passageiro.

Agora, neste exemplo, você poderia argumentar que a resposta não é realmente uma resposta como a pergunta era "o que é o propósito da porta do lado do passageiro?". Mas desde que a pergunta foi totalmente baseado em um equívoco da forma como as portas trabalhou não se segue que a refutação da premissa vai lançar uma nova luz sobre o objetivo da outra porta por dedução?

Aqui está uma peça do puzzle. Ele não explica por que você iria querer fazê-lo, mas não ajudam a explicar a diferença funcional.

Se você fixar a corda utilizando palavras-chave fixed, o conteúdo seria mutável. Em cima da minha cabeça, eu não consigo pensar em uma situação em que você iria querer fazer isso, mas é possível.

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);

Output:

Jello World
Jello World
Hello World

Uma busca rápida através do BCL for .NET 4.0 mostra que o método string.Copy é chamado em cerca de meia dúzia de lugares. Os usos cair em cerca nestas categorias:

  1. Para interoperabilidade com funções nativas que podem danificar as cordas passados ??para eles. Se você não pode afetar a declaração P / Invoke e você não pode fixar a função que está sendo chamado, string.Copy é a melhor escolha.

  2. Para situações onde a cadeia é modificado no local por motivos de desempenho. Se você precisa converter apenas alguns caracteres para minúsculas em uma potencialmente longa seqüência, a única maneira de fazê-lo sem copiar a cadeia duas vezes e criação de lixo adicional é a mutação-lo.

  3. Em locais onde não parece necessário. É bem possível que alguns programadores são mais utilizados para cordas Java ou C ++ e não percebem que copiar uma string em C # raramente é útil.

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

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

No entanto

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

Como a maneira de alguém se importa, eu acho que ele está lá para ser completo.


Além disso

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

Eu acho a vai ocupar mais memória RAM, em seguida, b, como a aponta para o buffer de tamanho 100 que o StringBuilder criado. (Olhe para o interior do método StringBuilder.ToString())


Eu acho StringBuilder faz uso de String.Copy() e fazer parte dos StringBuilderdoes .NET framework alterar o conteúdo do string. Assim, um string nem sempre é imutável.

Além do que tvanfosson disse (eu não acho que você pode acessar o buffer utilizado por uma corda gerido a partir de código não gerenciado ... Eu sei que seria difícil, pelo menos), eu acredito que pode haver uma diferença se a corda é usada como o objeto para fazer um bloqueio sobre a funcionalidade de vários segmentos.

Por exemplo ...

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
        }
    }
}

Eu acredito que se os dois métodos de exemplo são executados em paralelo, vão ser de bloqueio do mesmo objecto e, assim, um não será capaz de executar, enquanto a outra está dentro de seu bloco de bloqueio.

No entanto, se você alterá-lo para isto ...

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
        }
    }
}

Então eu acredito que eles só irá bloquear a execução de outros threads em execução o mesmo método (isto é, quaisquer threads em execução ExampleMethod1 será bloqueado até que cada concluída, mas eles não vão interferir com threads em execução ExampleMethod2).

Não sei se este é um útil diferença, uma vez que existem melhores mecanismos para a sincronização (Eu não acho que cordas de bloqueio é uma idéia muito boa).

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

auto-detecção de mudança?

Eu não sei como cordas a ser implementado em .NET, mas acho que Java é uma boa referência.

Em Java, new String (str) também fazer o que String.copy (str); que, alocar uma nova string com o mesmo valor.

O parecer inútil, mas é muito útil para otimização de memória.

cadeia contém um char [] com deslocamento e comprimento na implementação. Se você fizer um algo como um substring, ele não vai fazer uma cópia de memória, mas retornar um mesmo caractere nova partilha instância String []. Em muitos casos, este padrão vai economizar um monte de cópia de memória e alocação. No entanto, se você substring um pequeno pedaço dentro de uma grande cadeia longa. Vai ainda referência à grande char [] até mesmo a cadeia de grandes dimensões originais é 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

Pode forçar o novo objeto String alocar o seu próprio char [] para evitar escondida memória vazamento / resíduos.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top