Domanda

Ho paura che questa è una domanda molto stupida, ma devo essere manca qualcosa.

Perché potrebbe voler usare un String.Copy (stringa) ?

La documentazione dice che il metodo

  

Crea una nuova istanza di String con   lo stesso valore come stringa specificato.

Dal momento che le stringhe sono immutabili nel .NET, io non sono sicuro di quello che è il vantaggio di questo metodo, come mi piacerebbe pensare che

 string copy = String.Copy(otherString);

sarebbe a tutti gli effetti sembrano produrre lo stesso risultato di

 string copy = otherString;

Cioè, se non quella che la contabilità interna che sta succedendo, e il fatto che la copia non è ReferenceEquals a otherString, non ci sono differenze osservabili - String essendo una classe immutabile, la cui l'uguaglianza è basato sul valore, non identità. (Grazie a @Andrew Hare per aver ricordato che il mio fraseggio originale non era abbastanza preciso per indicare che ho capito che c'era una differenza tra Copy ING e non, ma era preoccupato per la percepita mancanza di utile differenza.)

Naturalmente quando viene passato un argomento null, Copy genera ArgumentNullException, e la "nuova istanza" potrebbe consumare più memoria. Quest'ultimo sembra quasi come un beneficio, e non sono sicuro che il controllo nulla è un grande bonus abbastanza da giustificare un intero metodo Copy.

Grazie.

È stato utile?

Soluzione

Con String.Copy in realtà si assegnano nuova memoria e copiare i caratteri da una stringa ad un altro; si ottiene una nuova istanza al contrario di avere entrambe le variabili che sono la stessa istanza. Questo può importa se si utilizza la stringa con il codice non gestito che si occupa con le posizioni di memoria direttamente e può mutare la stringa.

Altri suggerimenti

String.Copy restituisce un nuovo String e non produrrà gli stessi risultati come

String copy = otherString;

Prova questo:

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 si imposta test2 = test questi riferimenti puntano allo stesso Copy. La funzione <=> restituisce un nuovo riferimento <=> che ha le stesse contenuto ma come un oggetto diverso sul mucchio.


Modifica Ci sono un sacco di persone che sono abbastanza sconvolto che non ho risposto alla domanda del PO. Credo che ho fatto rispondere alla domanda correggendo una premessa errata nella domanda stessa. Ecco una analoga (se non semplificato) domanda e risposta che si spera illustrare il mio punto:

Domanda:

  

Ho notato che la mia macchina ha due porte, una su ogni lato della vettura. Credo che sia vero che, indipendentemente da quale porta che uso io finire seduto nel sedile del guidatore. Qual è lo scopo del l'altra porta?

Risposta:

  

In realtà non è vero che se si utilizza porta vi ritroverete nel posto di guida. Se si utilizza porta laterale del conducente si finirà nel posto di guida e se si utilizza porta lato passeggero si finirà nel sedile del passeggero.

Ora, in questo esempio, si potrebbe sostenere che la risposta non è proprio una risposta, come la domanda era "che cosa è lo scopo della porta lato passeggero?". Ma dal momento che la domanda è stata interamente basata su un equivoco di come le porte funzionavano non ne consegue che il rifiuto della premessa sarà gettare nuova luce sullo scopo l'altra porta per deduzione?

Ecco un pezzo del puzzle. Non spiega perché si vuole farlo, ma aiuta a spiegare una differenza funzionale.

Se si aggiunge la stringa utilizzando la parola chiave fixed, il contenuto sarebbe mutabile. Fuori della parte superiore della mia testa, non riesco a pensare a una situazione in cui si vorrebbe fare questo, ma è possibile.

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

Una rapida ricerca attraverso BCL per NET 4.0 dimostra che il metodo string.Copy viene chiamato in circa una mezza dozzina di posti. Gli usi rientrano in circa queste categorie:

  1. Per interoperabilità con funzioni native che possono danneggiare le stringhe passate a loro. Se non è possibile influenzare il P / Invoke dichiarazione e non è possibile correggere la funzione di essere chiamato, <=> è la scelta migliore.

  2. Per le situazioni in cui la corda viene modificato sul posto per motivi di prestazioni. Se avete bisogno di convertire solo alcuni caratteri in minuscolo in una potenzialmente lunga serie, l'unico modo per farlo senza copiare la stringa due volte e la creazione di ulteriore spazzatura è quello di mutare esso.

  3. Nei luoghi in cui non sembra necessario. E 'possibile che alcuni programmatori sono più abituati a stringhe Java o C ++ e non si rendono conto che la copia di una stringa in C # è raramente utile.

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

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

Tuttavia

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

Per quanto riguarda modo chiunque si cura, penso che sia lì per completezza.


Anche

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

Credo a occupano più RAM poi b, come StringBuilder punti nel buffer di dimensioni 100 che il StringBuilder.ToString() creato. (Guardate la parte interna del metodo String.Copy())


Credo string fa uso di <=> e di essere parte di .NET framework <=> fa cambiare il contenuto del <=>. Quindi un <=> non è sempre immutabile.

In aggiunta a quanto detto tvanfosson (non credo che si può accedere al buffer utilizzato da una stringa gestito da codice non gestito ... So che sarebbe stato difficile, almeno), credo che ci può essere una differenza, se la stringa viene utilizzato come oggetto per fare un blocco su per la funzionalità multithread.

Per esempio ...

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

Credo che se i due metodi di esempio vengono eseguite in parallelo, saranno chiudendo lo stesso oggetto e quindi non sarà in grado di eseguire mentre l'altra è all'interno del suo blocco serratura.

Tuttavia, se si cambia a questo ...

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

Poi Credo che bloccherà solo l'esecuzione di altri thread eseguono lo stesso metodo (cioè tutti i fili in esecuzione ExampleMethod1 sarà bloccato fino a quando ogni completa, ma non interferiranno con fili esecuzione ExampleMethod2).

Non sono sicuro che questo è un utile differenza, dal momento che ci sono meccanismi migliori per la sincronizzazione (non credo che le stringhe di blocco è una buona idea).

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

il rilevamento automatico cambiamento?

Non sono sicuro di come String in corso di attuazione in .NET, ma credo che Java è un buon riferimento.

In Java, new String (str) anche fare ciò che String.copy (str); do, allocare una nuova stringa con lo stesso valore.

E 'sembrare inutile, ma è molto utile per l'ottimizzazione della memoria.

String contiene un char [] con offset e lunghezza nella attuazione. Se si fa un qualcosa di simile a una stringa, che non farà una copia della memoria, ma restituire una nuova istanza String condividono lo stesso char []. In molti casi, questo modello farà risparmiare un sacco di copia della memoria e l'allocazione. Tuttavia, se si sottostringa un piccolo pezzo all'interno di una lunga stringa di grandi dimensioni. Sarà ancora riferimento a grandi char [] anche il grande stringa originale è in grado di essere 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

E 'possibile forzare il nuovo oggetto String allocare il proprio char [] per evitare perdita di memoria nascosta / rifiuti.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top