184 votes

Sortie de chaîne: format ou concat en C #?

Disons que vous voulez sortir ou concaténer des chaînes. Lequel des styles suivants préférez-vous?

  • var p = new { FirstName = "Bill", LastName = "Gates" };

  • Console.WriteLine("{0} {1}", p.FirstName, p.LastName);

  • Console.WriteLine(p.FirstName + " " + p.LastName);

Est-ce que vous préférez utiliser le format ou vous contentez-vous de concaténer des chaînes? Quel est ton préféré? Est-ce que l'un de ces problèmes vous fait mal aux yeux?

Avez-vous des arguments rationnels pour utiliser l'un et pas l'autre?

Je vais pour le deuxième.

161voto

Fredrik Kalseth Points 6633

Je suis étonné de voir que tant de gens immédiatement envie de trouver le code qui s'exécute de la manière la plus rapide. Si UN MILLION d'itérations ENCORE faut moins d'une seconde, est-ce vraiment va être en AUCUNE FAÇON perceptible pour l'utilisateur final? Pas très probable.

L'optimisation prématurée = ÉCHEC.

J'irais avec la Chaîne.Le Format de l'option, tout simplement parce qu'il fait le plus de sens à partir d'un point de vue architectural. Je ne m'inquiète pas au sujet de la performance jusqu'à ce qu'il devient réellement un problème (et si elle le faisait, je me pose: Dois-je vraiment besoin de concaténer un million de noms à la fois? Sûrement ils ne rentrent pas tous sur l'écran...)

Considérez si votre client désire modifier de sorte qu'il peut configurer que pour l'affichage de "Prénom Nom" ou "Nom, Prénom". Avec l'option de Format, c'est facile, il vous suffit de changer la chaîne de format. Avec la méthode concat, vous aurez besoin de code supplémentaire. Assurez-vous que ne pas sembler une grosse affaire dans cet exemple particulier, mais d'extrapoler.

89voto

Michał Piaskowski Points 2688

Essayez ce code.

C'est une version légèrement modifiée de votre code.
1. J'ai supprimé de la Console.WriteLine que c'est probablement quelques ordres de grandeur plus lent que ce que je suis en train de mesurer.
2. Je suis de regarder le Chronomètre avant la boucle et de l'arrêter tout de suite après, de cette façon, je ne suis pas perdant en précision si la fonction prend pour exemple 26.4 tiques à exécuter.
3. La façon dont vous avez divisé le résultat par le nombre d'itérations a été mauvais. Voir ce hapens si vous avez 1000 millisecondes et 100 millisecondes. Dans les deux cas, vous obtiendrez 0 ms après le divisant par 1000000.

    Stopwatch s = new Stopwatch();

    var p = new { FirstName = "Bill", LastName = "Gates" };

    int n = 1000000;
    long fElapsedMilliseconds = 0, fElapsedTicks = 0, cElapsedMilliseconds = 0, cElapsedTicks = 0;

    string result;
    s.Start();
    for (var i = 0; i < n; i++)
        result = (p.FirstName + " " + p.LastName);
    s.Stop();
    cElapsedMilliseconds = s.ElapsedMilliseconds;
    cElapsedTicks = s.ElapsedTicks;
    s.Reset();
    s.Start();
    for (var i = 0; i < n; i++)
        result = string.Format("{0} {1}", p.FirstName, p.LastName);
    s.Stop();
    fElapsedMilliseconds = s.ElapsedMilliseconds;
    fElapsedTicks = s.ElapsedTicks;
    s.Reset();


    Console.Clear();
    Console.WriteLine(n.ToString()+" x result = string.Format(\"{0} {1}\", p.FirstName, p.LastName); took: " + (fElapsedMilliseconds) + "ms - " + (fElapsedTicks) + " ticks");
    Console.WriteLine(n.ToString() + " x result = (p.FirstName + \" \" + p.LastName); took: " + (cElapsedMilliseconds) + "ms - " + (cElapsedTicks) + " ticks");
    Thread.Sleep(4000);

Ce sont mes résultats:

1000000 x result = string.Format("{0} {1}", p.FirstName, p.LastName); took: 618ms - 2213706 ticks
1000000 x result = (p.FirstName + " " + p.LastName); took: 166ms - 595610 ticks

54voto

samjudson Points 27483

Oh - après la lecture de l'une des autres réponses, j'ai essayé d'inverser l'ordre des opérations, d'effectuer la concaténation d'abord, puis de la Chaîne.Format de...

Bill Gates
Console.WriteLine(p.FirstName + " " + p.LastName); took: 8ms - 30488 ticks
Bill Gates
Console.WriteLine("{0} {1}", p.FirstName, p.LastName); took: 0ms - 182 ticks

Donc, l'ordre des opérations fait une ÉNORME différence, ou plutôt la première opération est TOUJOURS beaucoup plus lent.

Voici les résultats d'une course où les opérations sont terminées plus d'une fois. J'ai essayé de changer les commandes, mais les choses suivent en général les mêmes règles, une fois que le premier résultat est ignoré:

Bill Gates
Console.WriteLine(FirstName + " " + LastName); took: 5ms - 20335 ticks
Bill Gates
Console.WriteLine(FirstName + " " + LastName); took: 0ms - 156 ticks
Bill Gates
Console.WriteLine(FirstName + " " + LastName); took: 0ms - 122 ticks
Bill Gates
Console.WriteLine("{0} {1}", FirstName, LastName); took: 0ms - 181 ticks
Bill Gates
Console.WriteLine("{0} {1}", FirstName, LastName); took: 0ms - 122 ticks
Bill Gates
String.Concat(FirstName, " ", LastName); took: 0ms - 142 ticks
Bill Gates
String.Concat(FirstName, " ", LastName); took: 0ms - 117 ticks

Comme vous pouvez le voir les passages suivants de la même méthode (j'ai refait le code en 3 méthodes) sont progressivement plus rapide. La manière la plus rapide semble être la Console.WriteLine(String.Concat(...)) de la méthode, suivi par les normal de concaténation, et puis la mise en forme des opérations.

Le délai initial de démarrage est probablement l'initialisation de la Console de Flux, que la pose d'une Console.Writeline("Start!") avant la première opération apporte tous les temps de retour en ligne.

37voto

MrPhil Points 409

Les chaînes sont immuables, cela signifie que le même petit morceau de mémoire est utilisé encore et encore dans votre code. Ajouter les deux mêmes chaînes ensemble et créer la même nouvelle chaîne encore et encore n’a pas d’impact sur la mémoire. .Net est assez intelligent pour utiliser la même référence de mémoire. Par conséquent, votre code ne teste pas vraiment la différence entre les deux méthodes de concat.

Essayez ceci pour la taille:

 Stopwatch s = new Stopwatch();

int n = 1000000;
long fElapsedMilliseconds = 0, fElapsedTicks = 0, cElapsedMilliseconds = 0, cElapsedTicks = 0, sbElapsedMilliseconds = 0, sbElapsedTicks = 0;

Random random = new Random(DateTime.Now.Millisecond);

string result;
s.Start();
for (var i = 0; i < n; i++)
    result = (random.Next().ToString() + " " + random.Next().ToString());
s.Stop();
cElapsedMilliseconds = s.ElapsedMilliseconds;
cElapsedTicks = s.ElapsedTicks;
s.Reset();

s.Start();
for (var i = 0; i < n; i++)
    result = string.Format("{0} {1}", random.Next().ToString(), random.Next().ToString());
s.Stop();
fElapsedMilliseconds = s.ElapsedMilliseconds;
fElapsedTicks = s.ElapsedTicks;
s.Reset();

StringBuilder sb = new StringBuilder();
s.Start();
for(var i = 0; i < n; i++){
    sb.Clear();
    sb.Append(random.Next().ToString());
    sb.Append(" ");
    sb.Append(random.Next().ToString());
    result = sb.ToString();
}
s.Stop();
sbElapsedMilliseconds = s.ElapsedMilliseconds;
sbElapsedTicks = s.ElapsedTicks;
s.Reset();

Console.WriteLine(n.ToString() + " x result = string.Format(\"{0} {1}\", p.FirstName, p.LastName); took: " + (fElapsedMilliseconds) + "ms - " + (fElapsedTicks) + " ticks");
Console.WriteLine(n.ToString() + " x result = (p.FirstName + \" \" + p.LastName); took: " + (cElapsedMilliseconds) + "ms - " + (cElapsedTicks) + " ticks");
Console.WriteLine(n.ToString() + " x sb.Clear();sb.Append(random.Next().ToString()); sb.Append(\" \"); sb.Append(random.Next().ToString()); result = sb.ToString(); took: " + (sbElapsedMilliseconds) + "ms - " + (sbElapsedTicks) + " ticks");
Console.WriteLine("****************");
Console.WriteLine("Press Enter to Quit");
Console.ReadLine();
 

Échantillon sortie:

 1000000 x result = string.Format("{0} {1}", p.FirstName, p.LastName); took: 513ms - 1499816 ticks
1000000 x result = (p.FirstName + " " + p.LastName); took: 393ms - 1150148 ticks
1000000 x sb.Clear();sb.Append(random.Next().ToString()); sb.Append(" "); sb.Append(random.Next().ToString()); result = sb.ToString(); took: 405ms - 1185816 ticks
 

22voto

Jeremy McGee Points 13826

Pitié les pauvres traducteurs

Si vous savez que votre candidature restera en anglais, vous pouvez enregistrer les tics d'horloge. Cependant, de nombreuses cultures voient généralement le nom de famille Prénom, par exemple, dans les adresses.

Donc, utilisez string.Format() , surtout si votre candidature doit être diffusée partout où l'anglais n'est pas la première langue.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X