Frage

Ich habe Angst, dass dies eine sehr dumme Frage, aber ich muss etwas fehlt sein.

Warum könnte man verwenden möchten String.Copy (string) ?

Die Dokumentation sagt die Methode

  

Erstellt eine neue Instanz von String mit   der gleiche Wert wie ein angegebener String.

Da Strings unveränderlich in .NET sind, ich bin nicht sicher, was ist der Vorteil der Verwendung dieser Methode, wie ich denken würde, dass

 string copy = String.Copy(otherString);

wäre für alle praktischen Zwecke scheinen das gleiche Ergebnis wie

zu erhalten
 string copy = otherString;

Das heißt, außer für was auch immer internen Buchführung, die vor sich geht, und die Tatsache, dass nicht zu Other ReferenceEquals ist kopieren, gibt es keine beobachtbare Unterschiede - String eine unveränderliche Klasse zu sein, deren Gleichheit basiert auf Wert, nicht Identität. (Danke an @ Andrew Hare für den Hinweis auf, dass meine ursprüngliche Formulierung nicht präzise genug war, um anzuzeigen, dass ich erkennen es ein Unterschied zwischen Copying war und nicht, war aber besorgt über den wahrgenommenen Mangel an nützlich Unterschied.)

Natürlich, wenn ein null Argument übergibt, wirft Kopieren eine ArgumentNullException und die „neue Instanz“ möglicherweise mehr Speicher verbrauchen. Letzteres scheint kaum wie ein Vorteil, und ich bin nicht sicher, dass die Nullprüfung groß genug Bonus ist eine ganze Copy-Methode zu rechtfertigen.

Danke.

War es hilfreich?

Lösung

Mit String.Copy Sie Zuteilung tatsächlich neue Speicher und Kopieren der Zeichen aus einer Zeichenfolge zu einem anderen; Sie erhalten eine völlig neue Instanz als beide Variablen im Gegensatz zu sein dieselbe Instanz zu haben. Dies kann aus, wenn Sie die Zeichenfolge mit nicht verwalteten Code verwenden, die direkt mit den Speicherplätzen beschäftigt und die Zeichenfolge mutieren kann.

Andere Tipps

String.Copy gibt ein neues String und führt nicht die gleichen Ergebnisse wie

String copy = otherString;

Versuchen Sie folgendes:

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

Wenn Sie setzen test2 = test zeigen diese Verweise auf die gleiche String. Die Copy Funktion gibt eine neue String Referenz, die den gleichen Inhalt hat , sondern als ein anderes Objekt auf dem Heap.


Edit: Es gibt eine Menge Leute, die ziemlich sauer sind, dass ich nicht die OP Frage antwortete. Ich glaube, dass ich die Frage beantworten, tat sich allein eine falsche Prämisse in Frage zu korrigieren. Hier ist eine analoge (wenn nicht zu stark vereinfacht) Frage und Antwort, die hoffentlich meinen Punkt illustrieren wird:

Frage:

  

Ich habe beobachtet, dass mein Auto hat zwei Türen, eine auf jeder Seite des Autos. Ich glaube, es wahr zu sein, dass unabhängig von der Tür Ich benutze ich werde in den Fahrersitz sitzt am Ende. Was ist der Zweck der anderen Tür?

Antwort:

  

Eigentlich ist es nicht wahr, dass, wenn Sie entweder Tür verwenden, werden Sie in den Fahrersitz enden. Wenn Sie die Fahrerseitentür verwenden, werden Sie in den Fahrersitz und am Ende, wenn Sie die Seitentür des Passagiers verwenden, werden Sie auf dem Beifahrersitz enden.

Nun in diesem Beispiel könnte man argumentieren, dass die Antwort nicht wirklich eine Antwort ist wie die Frage war „was der Zweck der Seitentür des Passagiers ist?“. Da aber die ganz Frage auf einem Missverständnis der beruhte, wie die Türen gearbeitet folgt daraus nicht, dass die Widerlegung der Prämisse auf dem Zweck der anderen Tür durch Abzug neues Licht wird?

Hier ist ein Stück des Puzzles. Es erklärt nicht, warum Sie es tun wollen würden, aber es hilft einen funktionellen Unterschied zu erklären.

Wenn Sie die Zeichenfolge Pin das fixed Schlüsselwort verwenden, würde der Inhalt wandelbar sein. Aus der Spitze von meinem Kopf, kann ich glaube nicht an einer Situation, in der Sie wollen würden, dies zu tun, aber es ist möglich.

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

Ausgabe:

Jello World
Jello World
Hello World

Eine schnelle Suche durch die BCL für .NET 4.0 zeigt, dass die string.Copy Verfahren in etwa einem halben Dutzend Orte genannt wird. Die Nutzungen fallen grob in diesen Kategorien:

  1. Für Interop mit nativen Funktionen, die die Saiten übergeben, um sie beschädigen können. Wenn Sie die P / Invoke Erklärung beeinflussen können, und Sie können die Funktion wird aufgerufen, sich nicht beheben lassen, string.Copy ist die beste Wahl.

  2. Für Situationen, in denen die Zeichenfolge an Ort und Stelle aus Performance-Gründen geändert werden. Wenn Sie nur ein paar Zeichen konvertieren müssen in einer möglicherweise langen String in Kleinbuchstaben, die einzige Möglichkeit, so zu tun, ohne das Kopieren der Zeichenfolge zweimal und die Schaffung zusätzlicher Müll ist es zu mutieren.

  3. In Orten, wo es nicht notwendig erscheint. Es ist durchaus möglich, dass einige Programmierer mehr verwendet werden, um Java oder C ++ Strings und nicht erkennen, dass eine Zeichenfolge in C # Kopieren ist selten sinnvoll.

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

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

Allerdings

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

In Bezug auf Art und Weise jemand kümmern, ich denke, es gibt für Vollständigkeit ist.


Auch

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

Ich denke, a wird mehr RAM nehmen dann b, wie a zeigt auf den Puffer der Größe 100, die die StringBuilder erstellt. (Blick auf der Innenseite der StringBuilder.ToString() Methode)


Ich denke, StringBuilder Verwendung von String.Copy() und Teil des .NET-Frameworks StringBuilderdoes den Inhalt der string macht ändern. So ein string ist nicht immer unveränderlich.

Zusätzlich zu dem, was tvanfosson sagte (ich glaube nicht, dass Sie den Puffer von einem verwalteten Zeichenfolge von nicht verwalteten Code verwendete zugreifen können ... Ich weiß, dass es schwierig sein würde, zumindest), ich glaube, dass es ein Unterschied sein kann, wenn die Zeichenfolge als das Objekt verwendet, um eine Sperre auf für Multi-Thread-Funktionalität zu tun.

Zum Beispiel ...

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

Ich glaube, wenn die zwei beispielhaften Verfahren parallel ausgeführt werden, werden sie auf das gleiche Objekt werden Verriegelungs- und somit wird man nicht in der Lage sein, auszuführen, während die andere in seinem Verriegelungsblock ist.

Allerdings, wenn Sie es das ändern ...

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

dann glaube ich, dass sie nur die Ausführung anderer Threads blockieren, wird das gleiche Verfahren ausgeführt wird (das heißt keine Threads ausführt ExampleMethod1 gesperrt werden, bis jeder abgeschlossen ist, aber sie werden nicht mit einem Gewinde interferieren läuft ExampleMethod2).

Nicht sicher, dies ist ein nützlich Unterschied, da es bessere Mechanismen für die Synchronisation (ich glaube nicht, Saiten Verriegelung ist eine sehr gute Idee).

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

Auto-Änderungserkennung?

Ich bin nicht sicher, wie String in .NET implementiert werden, aber ich denke, Java eine gute Referenz ist.

In Java, new String (str) auch tun, was String.copy (str); Sie, ein neues String mit dem gleichen Wert zuweisen.

Es scheint sinnlos, aber es ist sehr nützlich bei der Speicheroptimierung.

String enthält ein char [] mit Offset und Länge in der Umsetzung. Wenn Sie ein etwas wie ein Teilzeichen tun, wird es keine Speicherkopie tun, sondern eine neue String-Instanz teilt gleiche char [] zurückzukehren. In vielen Fällen wird dieses Muster eine Menge Speicher zu kopieren und die Zuweisung speichern. Wenn Sie jedoch ein kleines Stück innerhalb eines langen großen String String. Es wird immer noch zu groß char Referenz [] sogar das ursprüngliche große String der Lage ist, GC zu sein.

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

Es kann das neuen String zwingt Objekt zuweisen seine eigene char [] verstecktes Speicherleck / Abfall zu vermeiden.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top