Question

Je crains que ce soit une question très stupide, mais je dois manquer quelque chose.

Pourquoi peut-on vouloir utiliser String.Copy (string) ?

La documentation indique la méthode

  

Crée une nouvelle instance de chaîne avec   la même valeur en tant que chaîne spécifiée.

Puisque les chaînes sont immuables dans .NET, je ne sais pas quel est l'avantage de cette méthode, comme je pense que

 string copy = String.Copy(otherString);

seraient à toutes fins pratiques semblent donner le même résultat que

 string copy = otherString;

C'est, sauf pour quelque comptabilité interne qui se passe, et le fait que la copie ne soit pas à otherString ReferenceEquals, il n'y a pas de différences observables - chaîne étant une classe immuable dont l'égalité est fondée sur la valeur, et non l'identité. (Merci à Hare pour @ Andrew rappelant que mon phrasé original était pas assez précis pour indiquer que je me suis aperçu qu'il y avait une différence entre et non Copy ment, mais il était préoccupé par le manque perçu de utile différence).

Bien sûr, lorsqu'il est passé un argument null, Copie lève une ArgumentNullException, et la « nouvelle instance » pourrait consommer plus de mémoire. Ce dernier ne semble guère comme un avantage, et je ne suis pas sûr que le chèque nul est un bonus assez grand pour justifier une méthode de copie tout.

Merci.

Était-ce utile?

La solution

Avec vous allouez String.Copy en fait une nouvelle mémoire et copier les caractères d'une chaîne à l'autre; vous obtenez une instance complètement nouveau plutôt que d'avoir les deux variables étant la même instance. Cela peut importe si vous utilisez la chaîne avec le code non géré qui traite des emplacements de mémoire directement et peut muter la chaîne.

Autres conseils

String.Copy retourne une nouvelle et ne cède String pas les mêmes résultats que

String copy = otherString;

Essayez ceci:

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

Lorsque vous définissez ces références pointent test2 = test à la même Copy. La fonction retourne une nouvelle <=> référence qui a les <=> mêmes contenu mais comme un objet différent sur le tas.


Modifier Il y a beaucoup de gens qui sont assez en colère que je ne l'ai pas répondu à la question de l'OP. Je crois que j'ai répondu à la question en corrigeant une prémisse erronée dans la question elle-même. Voici une question et une réponse analogue (sinon simpliste) qui nous l'espérons illustrer mon point:

Question:

  

J'ai remarqué que ma voiture a deux portes, une de chaque côté de la voiture. Je crois qu'il est vrai que quelle que soit la porte, je l'utilise, je vais finir par assis dans le siège du conducteur. Quel est le but de l'autre porte?

Réponse:

  

En fait, il est pas vrai que si vous utilisez l'une des portes, vous finirez dans le siège du conducteur. Si vous utilisez la porte du côté du conducteur, vous finirez dans le siège du conducteur et si vous utilisez la porte du côté du passager, vous finirez dans le siège du passager.

Dans cet exemple, on pourrait dire que la réponse est pas vraiment une réponse que la question était « quel est le but de la porte du côté passager? ». Mais puisque cette question était entièrement basée sur une conception erronée de la façon dont les portes ont travaillé, il ne suit pas que la réfutation de la prémisse va permettre de mieux sur le but de l'autre porte par déduction?

Voici une pièce du puzzle. Il n'explique pas pourquoi vous voulez le faire, mais il ne permet d'expliquer une différence fonctionnelle.

Si vous épinglez la chaîne en utilisant le mot-clé fixed, le contenu serait muable. Du haut de ma tête, je ne peux pas penser à une situation dans laquelle vous voulez faire, mais il est possible.

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

Sortie:

Jello World
Jello World
Hello World

Une recherche rapide par la BCL pour .NET 4.0 montre que la méthode est appelée dans string.Copy environ une demi-douzaine d'endroits. Les usages se divisent en environ ces catégories:

  1. Pour Interop avec des fonctions natives qui peuvent endommager les chaînes transmises à eux. Si vous ne pouvez pas affecter la déclaration P / Invoke et vous ne pouvez pas fixer la fonction appelée, est le meilleur <=> choix.

  2. Pour les situations où la chaîne est modifiée en place pour des raisons de performance. Si vous avez besoin de convertir la seule façon de faire quelques caractères en minuscules dans une chaîne potentiellement longue, sans copier deux fois la chaîne et la création d'ordures supplémentaires est de muter.

  3. Dans les endroits où il ne semble pas nécessaire. Il est tout à fait possible que certains programmeurs sont plus habitués à Java ou C ++ chaînes et ne réalisent pas que la copie d'une chaîne en C # est rarement utile.

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

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

Cependant

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

Quant à façon quelqu'un va prendre soin, je pense qu'il est là pour être complet.


Aussi

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

Je pense que prendra a plus de RAM puis b, comme des points au StringBuilder buffer de taille 100 que la création StringBuilder.ToString(). (Voir l'intérieur de la méthode String.Copy())


Je pense que utilise string et faisant partie <=> du framework .NET ne change <=> le contenu du <=>. Ainsi, un est pas toujours <=> immuable.

En plus de ce que tvanfosson dit (je ne pense pas que vous pouvez accéder à la mémoire tampon utilisé par une chaîne gérée à partir du code non géré ... Je sais que ce serait difficile, au moins), je crois qu'il peut y avoir une différence si la chaîne est utilisée comme objet de faire un verrou sur la fonctionnalité multithread.

Par exemple ...

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

Je crois que si les deux méthodes d'exemple sont exécutés en parallèle, ils seront verrouillent le même objet et donc on ne sera pas en mesure d'exécuter tandis que l'autre est à l'intérieur de son bloc de verrouillage.

Toutefois, si vous le changiez à cette ...

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

Alors, je crois qu'ils ne bloquer l'exécution d'autres threads d'exécution de la même méthode (à savoir les fils d'exécution ExampleMethod1 sera verrouillé jusqu'à ce que chaque terminée, mais ils ne vont pas interférer avec les discussions en cours d'exécution ExampleMethod2).

Je ne sais pas c'est un utile différence, car il existe de meilleurs mécanismes de synchronisation (je ne pense pas que le verrouillage des chaînes est une très bonne idée).

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

Détection automatique de changement?

Je ne sais pas comment chaîne en cours d'exécution dans .NET, mais je pense que Java est une bonne référence.

En Java, new String (str) font aussi ce que String.copy (str); faire, allouer une nouvelle chaîne avec la même valeur.

Il semble inutile, mais il est très utile dans l'optimisation de la mémoire.

chaîne contient un char [] avec un décalage et une longueur dans la mise en œuvre. Si vous faites quelque chose comme une sous-chaîne, il ne fera pas une copie de la mémoire, mais retourner une nouvelle instance String partage même char []. Dans de nombreux cas, ce modèle permettra d'économiser beaucoup de mémoire copie et de l'allocation. Toutefois, si vous substring un petit morceau dans une longue chaîne de grande taille. Il sera toujours la référence à un grand char [], même le grand String original peut être 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

Il peut forcer le nouvel objet String allouer son propre char [] pour empêcher la fuite / déchets de mémoire cachée.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top