183

文字列を出力または連結したいとしましょう。次のどのスタイルが好きですか?

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

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

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

フォーマットを使用しますか、それとも単純に文字列を連結しますか? あなたのお気に入りは?これらのいずれかがあなたの目を傷つけていますか?

一方を使用し、他方を使用しないという合理的な議論はありますか?

私は2番目のものに行きます。

4

32 に答える 32

161

非常に多くの人が、最も速く実行されるコードをすぐに見つけたいと思っていることに驚いています。100 万回の繰り返しの処理に 1 秒もかからない場合、これは何らかの方法でエンド ユーザーに認識されるでしょうか? あまりありません。

時期尚早の最適化 = 失敗。

String.Formatアーキテクチャの観点から最も理にかなっているという理由だけで、このオプションを使用します。パフォーマンスが問題になるまでは気にしません (パフォーマンスが問題になる場合は、一度に 100 万の名前を連結する必要があるかどうかを自問します。画面にすべてが収まらないことは確かです...)

顧客が後で表示するかどうかを構成できるように変更するかどうかを検討してください"Firstname Lastname"または"Lastname, Firstname."フォーマットオプションを使用すると、これは簡単です-フォーマット文字列を交換するだけです. concat を使用すると、追加のコードが必要になります。確かに、この特定の例では大したことではないように聞こえますが、推定してください。

于 2008-08-23T20:07:13.893 に答える
89

このコードを試してください。

これは、コードのわずかに変更されたバージョンです。

  1. Console.WriteLine は、おそらく測定しようとしているものよりも数桁遅いため、削除しました。
  2. ループの前にストップウォッチを開始し、直後に停止しています。このようにして、関数の実行にたとえば 26.4 ティックかかる場合でも、精度が失われることはありません。
  3. 結果をいくつかの反復で割る方法が間違っていました。1,000 ミリ秒と 100 ミリ秒があるとどうなるか見てみましょう。どちらの状況でも、1,000,000 で割ると 0 ミリ秒になります。

コード:

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

それらは私の結果です:

1000000 x 結果 = string.Format("{0} {1}", p.FirstName, p.LastName); かかった: 618ms - 2213706 ティック
1000000 x 結果 = (p.FirstName + " " + p.LastName); かかった時間: 166ms - 595610 ティック

于 2008-08-20T16:40:14.973 に答える
54

親愛なる-他の返信の1つを読んだ後、操作の順序を逆にしてみました-最初に連結を実行し、次にString.Format ...

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

したがって、操作の順序によって大きな違いが生じます。つまり、最初の操作は常にはるかに遅くなります。

以下は、操作が複数回完了した実行の結果です。順序を変更してみましたが、最初の結果が無視されると、通常は同じルールに従います。

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

ご覧のとおり、同じメソッド (コードを 3 つのメソッドにリファクタリングしました) の後続の実行は、段階的に高速化されています。最速は Console.WriteLine(String.Concat(...)) メソッドで、通常の連結、フォーマットされた操作が続きます。

起動時の最初の遅延は、最初の操作がすべての時間を元に戻す前に Console.Writeline("Start!") を配置するため、コンソール ストリームの初期化である可能性があります。

于 2008-08-20T08:45:19.563 に答える
37

文字列は不変です。これは、コード内で同じ小さなメモリが何度も使用されることを意味します。同じ 2 つの文字列を一緒に追加して、同じ新しい文字列を何度も作成しても、メモリには影響しません。.Net は、同じメモリ参照を使用するだけで十分スマートです。したがって、コードは 2 つの concat メソッドの違いを真にテストしていません。

これを試着してサイズを確認してください:

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

サンプル出力:

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
于 2012-11-13T01:13:15.097 に答える
22

貧しい翻訳者に同情する

アプリケーションが英語のままであることがわかっている場合は、時計の目盛りを保存してください。ただし、多くの文化では通常、住所などに Lastname Firstname が表示されます。

したがってstring.Format()、特にアプリケーションを英語が第一言語ではない場所に移動させる場合は、 を使用してください。

于 2009-11-30T21:11:53.920 に答える
14

これが100,000回の反復での私の結果です。

Console.WriteLine("{0} {1}", p.FirstName, p.LastName); took (avg): 0ms - 689 ticks
Console.WriteLine(p.FirstName + " " + p.LastName); took (avg): 0ms - 683 ticks

そして、ここにベンチコードがあります:

Stopwatch s = new Stopwatch();

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

//First print to remove the initial cost
Console.WriteLine(p.FirstName + " " + p.LastName);
Console.WriteLine("{0} {1}", p.FirstName, p.LastName);

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

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

Console.Clear();

Console.WriteLine("Console.WriteLine(\"{0} {1}\", p.FirstName, p.LastName); took (avg): " + (fElapsedMilliseconds / n) + "ms - " + (fElapsedTicks / n) + " ticks");
Console.WriteLine("Console.WriteLine(p.FirstName + \" \" + p.LastName); took (avg): " + (cElapsedMilliseconds / n) + "ms - " + (cElapsedTicks / n) + " ticks");

だから、誰の返事が答えとしてマークするのかわかりません:)

于 2008-08-20T16:16:31.537 に答える
9

文字列の連結は、そのような単純なシナリオでは問題ありません。LastName や FirstName など、それよりも複雑なシナリオではさらに複雑になります。コードを読み取ったときに文字列の最終的な構造がどのようなものになるかが一目でわかる形式では、連結では最終結果をすぐに識別することはほとんど不可能になります (このような非常に単純な例を除いて)。

長い目で見れば、文字列フォーマットを変更するために戻ってきたときに、ポップインしてフォーマット文字列にいくつかの調整を加えるか、眉をひそめてすべてを動かし始めることができるということです。さまざまな種類のプロパティ アクセサーがテキストと混在しているため、問題が発生する可能性が高くなります。

.NET 3.5 を使用している場合は、このような拡張メソッドを使用して、次のようなカフ構文から簡単に流れるようにすることができます。

string str = "{0} {1} is my friend. {3}, {2} is my boss.".FormatWith(prop1,prop2,prop3,prop4);

最後に、アプリケーションが複雑になるにつれて、アプリケーション内の文字列を適切に維持するために、文字列をリソース ファイルに移動してローカライズするか、単に静的ヘルパーに移動することを決定する場合があります。一貫してフォーマットを使用していれば、これははるかに簡単に達成でき、コードは次のようなものを使用するように非常に簡単にリファクタリングできます。

string name = String.Format(ApplicationStrings.General.InformalUserNameFormat,this.FirstName,this.LastName);
于 2008-08-19T15:56:23.377 に答える
8

C# から始めて、6.0 補間された文字列を使用してこれを行うことができるため、フォーマットがさらに簡素化されます。

var name = "Bill";
var surname = "Gates";
MessageBox.Show($"Welcome to the show, {name} {surname}!");

補間された文字列式は、式を含むテンプレート文字列のように見えます。補間された文字列式は、含まれている式を式の結果の ToString 表現に置き換えることによって文字列を作成します。

補間された文字列は String.Format と同様のパフォーマンスを持ちますが、値と式がインラインで挿入されるため、読みやすさが向上し、構文が短くなります。

文字列補間に関するこの dotnetperls の記事も参照してください。

文字列をフォーマットするデフォルトの方法を探している場合、これは読みやすさとパフォーマンスの点で理にかなっています (特定のユースケースでマイクロ秒が違いを生む場合を除く)。

于 2015-08-07T23:32:12.663 に答える
7

非常に単純な操作には連結を使用しますが、要素が 2 つまたは 3 つを超えると、形式がより適切な IMO になります。

String.Format を優先するもう 1 つの理由は、.NET 文字列は不変であり、この方法で作成すると一時/中間コピーが少なくなることです。

于 2008-08-19T15:50:44.170 に答える
6

私はスタイルの好みを完全に理解しており、最初の回答に連結を選択しましたが、これは私自身の好みにも基づいていましたが、私の決定の一部は、連結の方が高速であるという考えに基づいていました。好奇心からテストしたところ、結果は驚くべきものでした。特に、このような小さな文字列の場合はそうでした。

次のコードを使用します。

    System.Diagnostics.Stopwatch s = new System.Diagnostics.Stopwatch();

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

    s.Start();
    Console.WriteLine("{0} {1}", p.FirstName, p.LastName);
    s.Stop();
    Console.WriteLine("Console.WriteLine(\"{0} {1}\", p.FirstName, p.LastName); took: " + s.ElapsedMilliseconds + "ms - " + s.ElapsedTicks + " ticks");

    s.Reset();
    s.Start();
    Console.WriteLine(p.FirstName + " " + p.LastName);
    s.Stop();

    Console.WriteLine("Console.WriteLine(p.FirstName + \" \" + p.LastName); took: " + s.ElapsedMilliseconds + "ms - " + s.ElapsedTicks + " ticks");

次の結果が得られました。

Bill Gates
Console.WriteLine("{0} {1}", p.FirstName, p.LastName); took: 2ms - 7280 ticks
Bill Gates
Console.WriteLine(p.FirstName + " " + p.LastName); took: 0ms - 67 ticks

フォーマット方法を使用すると、100倍以上遅くなります!! 連結は1ミリ秒としても登録されませんでした。そのため、タイマーティックも出力しました。

于 2008-08-19T16:02:27.967 に答える
5

一般的に、私は前者を好みます。特に文字列が長くなると読みやすくなるからです。

もう1つの利点は、パフォーマンスの1つだと思います。後者は、最終的な文字列をConsole.Writeメソッドに渡す前に実際に2つの文字列作成ステートメントを実行するからです。String.Format私が信じているカバーの下で StringBuilder を使用しているため、複数の連結は回避されます。

ただし、渡すパラメーターString.Format(および Console.Write などの他のメソッド) が値型の場合、それらは渡される前にボックス化されるため、独自のパフォーマンス ヒットが発生する可能性があることに注意してください。これに関するブログ投稿はこちら.

于 2008-08-19T15:53:59.060 に答える
5

基本的な文字列連結の場合、私は通常、読みやすくシンプルな 2 番目のスタイルを使用します。ただし、より複雑な文字列の組み合わせを行う場合は、通常 String.Format を選択します。

String.Format は、多くの引用符とプラスを節約します...

Console.WriteLine("User {0} accessed {1} on {2}.", user.Name, fileName, timestamp);
vs
Console.WriteLine("User " + user.Name + " accessed " + fileName + " on " + timestamp + ".");

ほんの数文字しか保存されていませんが、この例では、フォーマットによってはるかにきれいになっていると思います。

于 2008-08-19T15:55:01.273 に答える
5

2015 年 8 月 19 日から 1 週間で、この質問はちょうど 7 年前のものになります。現在、これを行うためのより良い方法があります。文字列を連結するだけと比較して、パフォーマンステストを行っていないため、保守性の点で優れています(ただし、最近は問題になりますか?数ミリ秒の違いがありますか?)。C# 6.0でそれを行う新しい方法:

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

この新しい機能は、IMO の方が優れており、値がいくつかの要因に依存するクエリ文字列を作成するコードがあるため、実際は私たちのケースではより優れています。6 つの引数を持つ 1 つのクエリ文字列を想像してみてください。したがって、次のようにする代わりに、次のようにします。

var qs = string.Format("q1={0}&q2={1}&q3={2}&q4={3}&q5={4}&q6={5}", 
    someVar, anotherVarWithLongName, var3, var4, var5, var6)

in は次のように書くことができ、読みやすくなります。

var qs=$"q1={someVar}&q2={anotherVarWithLongName}&q3={var3}&q4={var4}&q5={var5}&q6={var6}";
于 2015-08-12T03:18:07.657 に答える
5

より良いテストは、Perfmon と CLR メモリ カウンターを使用してメモリを監視することです。私の理解では、文字列を連結するだけでなく String.Format を使用する理由は、文字列が不変であるため、次のパスで再利用する必要がある一時的な文字列をガベージ コレクターに不必要に負担させていることです。

StringBuilder と String.Format は、遅くなる可能性がありますが、メモリ効率が高くなります。

文字列連結の何が悪いのでしょうか?

于 2008-09-22T14:27:23.543 に答える
4
  1. フォーマットは、それを行う「.NET」の方法です。特定のリファクタリング ツール (Refactor! など) は、concat スタイルのコードをリファクタリングして書式設定スタイルを使用することを提案します。
  2. 書式設定は、コンパイラ用に最適化する方が簡単です (ただし、2 つ目は、高速な「Concat」メソッドを使用するようにリファクタリングされる可能性があります)。
  3. 通常、書式設定は読みやすくなります (特に「凝った」書式設定の場合)。
  4. フォーマットとは、すべての変数で「.ToString」への暗黙的な呼び出しを意味するため、読みやすくなります。
  5. 「Effective C#」によると、.NET の 'WriteLine' と 'Format' の実装がめちゃくちゃで、すべての値の型を自動ボックス化します (これは悪いことです)。「Effective C#」は、'.ToString' 呼び出しを明示的に実行するようにアドバイスしていますが、これは偽物です ( Jeff の投稿を参照) 。
  6. 現時点では、型ヒントの書式設定はコンパイラによってチェックされないため、実行時エラーが発生します。ただし、これは将来のバージョンで修正される可能性があります。
于 2008-08-19T15:59:21.623 に答える
4

を使用しますString.Formatが、他の言語にローカライズできるように、リソース ファイルに書式文字列も含めます。単純な文字列 concat を使用しても、それはできません。明らかに、その文字列をローカライズする必要がない場合、これはそれについて考える理由にはなりません。それは本当に文字列が何のためにあるかに依存します。

ユーザーに表示する場合は、String.Format必要に応じてローカライズできるように使用します-念のため、FxCopがスペルチェックを行います:)

数値またはその他の文字列以外のもの (日付など) が含まれている場合は、書式設定をString.Formatより細かく制御できるため、使用します。

SQL のようなクエリを作成する場合は、Linqを使用します。

ループ内で文字列を連結する場合は、パフォーマンスの問題を回避するためにStringBuilderを使用します。

ユーザーが表示せず、パフォーマンスに影響を与えない出力の場合は、 String.Format を使用します。とにかく使用する習慣があり、慣れているだけだからです:)

于 2008-08-19T16:06:37.880 に答える
4

読みやすさで選んでいます。変数の周りにテキストがある場合は、フォーマット オプションを好みます。この例では:

Console.WriteLine("User {0} accessed {1} on {2}.", 
                   user.Name, fileName, timestamp);

変数名がなくても意味を理解できますが、連結は引用符と + 記号で雑然としていて、私の目を混乱させます。

Console.WriteLine("User " + user.Name + " accessed " + fileName + 
                  " on " + timestamp + ".");

(マイクさんの作例が好きなのでお借りしました)

フォーマット文字列が変数名なしではあまり意味がない場合は、concat を使用する必要があります。

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

format オプションを使用すると、変数名を読み取って対応する番号にマップできます。concat オプションはそれを必要としません。私はまだ引用符と + 記号に混乱していますが、別の方法の方が悪いです。ルビー?

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

パフォーマンスに関しては、フォーマットでは文字列を解析する必要があるため、フォーマット オプションは concat よりも遅くなると思います。この種の命令を最適化する必要があったことを覚えていませんが、最適化した場合は、や などのstringメソッドを調べます。Concat()Join()

このフォーマットのもう 1 つの利点は、フォーマット文字列を構成ファイルに入れることができることです。エラー メッセージと UI テキストで非常に便利です。

于 2009-05-13T08:35:59.430 に答える
3

結果をローカライズする場合は、String.Format が不可欠です。異なる自然言語では、データが同じ順序でさえない可能性があるためです。

于 2009-06-07T14:50:08.567 に答える
3

読みやすくする必要があるもの (そしてこれがほとんどのコード) を扱っている場合は、次の場合を除き、演算子のオーバーロード バージョンを使用します。

  • コードは何百万回も実行する必要があります
  • 大量の連結を行っています (4 つ以上は 1 トンです)
  • コードは Compact Framework を対象としています

これらの状況のうち少なくとも 2 つでは、代わりに StringBuilder を使用します。

于 2008-09-22T14:43:54.937 に答える
2

良いですね!

追加したばかり

        s.Start();
        for (var i = 0; i < n; i++)
            result = string.Concat(p.FirstName, " ", p.LastName);
        s.Stop();
        ceElapsedMilliseconds = s.ElapsedMilliseconds;
        ceElapsedTicks = s.ElapsedTicks;
        s.Reset();

そしてそれはさらに高速です(両方の例でstring.Concatが呼び出されていると思いますが、最初の例では何らかの変換が必要です)。

1000000 x result = string.Format("{0} {1}", p.FirstName, p.LastName); took: 249ms - 3571621 ticks
1000000 x result = (p.FirstName + " " + p.LastName); took: 65ms - 944948 ticks
1000000 x result = string.Concat(p.FirstName, " ", p.LastName); took: 54ms - 780524 ticks
于 2008-08-20T18:07:42.207 に答える
2

これは、出力の複雑さに大きく依存すると思います。私は、その時点で最も効果的なシナリオを選択する傾向があります。

仕事に基づいて適切なツールを選択してください :D 最もきれいに見えるものはどれでも!

于 2008-08-19T15:50:34.933 に答える
2

私も後者を好みますが、現時点ではその立場を支持する合理的な議論はありません。

于 2008-08-19T15:51:26.537 に答える
1

MCSDの準備資料によると、Microsoftは、非常に少数の連結(おそらく2から4)を処理する場合は、+演算子を使用することをお勧めします。理由はまだわかりませんが、検討する必要があります。

于 2009-07-04T20:31:04.130 に答える
1

最初のもの(フォーマット)は私にはよく見えます。読みやすく、余分な一時文字列オブジェクトを作成していません。

于 2008-08-23T19:55:24.247 に答える
1

私はいつも string.Format() ルートに行きました。Nathan の例のようにフォーマットを変数に格納できることは大きな利点です。場合によっては、変数を追加することもありますが、複数の変数が連結されると、フォーマットを使用するようにリファクタリングします。

于 2008-08-19T19:16:49.043 に答える
1

ああ、完全を期すために、以下は通常の連結よりも数ティック高速です。

Console.WriteLine(String.Concat(p.FirstName," ",p.LastName));
于 2008-08-20T08:38:11.343 に答える
1

テキストに多くの変数が混ざり合っていると、読みやすくなるので、実際には最初のものが好きです。さらに、string.Format() フォーマットを使用すると、引用符を簡単に処理できます。これは、文字列連結の適切な分析です。

于 2008-08-19T15:57:20.567 に答える
1

個人的には、2 番目のものは、使用しているものすべてが出力される直接の順序になっています。一方、最初のものでは、{0} と {1} を適切な変数と一致させる必要があり、混乱しやすいです。

少なくとも、変数の型を間違えるとすべてが爆発する C++ スプリントほど悪くはありません。

また、2 番目はすべてインラインであり、すべての {0} を検索および置換する必要がないため、後者の方が高速であるはずです...確かなことはわかりませんが。

于 2008-08-19T15:49:57.010 に答える
1

StringBuilder がこれらのテストでどのような立場にあったのか興味がありました。以下の結果...

class Program {
   static void Main(string[] args) {

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

      var tests = new[] {
         new { Name = "Concat", Action = new Action(delegate() { string x = p.FirstName + " " + p.LastName; }) },
         new { Name = "Format", Action = new Action(delegate() { string x = string.Format("{0} {1}", p.FirstName, p.LastName); }) },
         new { Name = "StringBuilder", Action = new Action(delegate() {
            StringBuilder sb = new StringBuilder();
            sb.Append(p.FirstName);
            sb.Append(" ");
            sb.Append(p.LastName);
            string x = sb.ToString();
         }) }
      };

      var Watch = new Stopwatch();
      foreach (var t in tests) {
         for (int i = 0; i < 5; i++) {
            Watch.Reset();
            long Elapsed = ElapsedTicks(t.Action, Watch, 10000);
            Console.WriteLine(string.Format("{0}: {1} ticks", t.Name, Elapsed.ToString()));
         }
      }
   }

   public static long ElapsedTicks(Action ActionDelg, Stopwatch Watch, int Iterations) {
      Watch.Start();
      for (int i = 0; i < Iterations; i++) {
         ActionDelg();
      }
      Watch.Stop();
      return Watch.ElapsedTicks / Iterations;
   }
}

結果:

連結: 406 ティック
連結: 356 ティック
連結: 411 ティック
連結: 299 ティック
連結: 266 ティック
フォーマット: 5269 ティック
フォーマット: 954 ティック
フォーマット: 1004 ティック
フォーマット: 984 ティック
フォーマット: 974 ティック
StringBuilder: 629 ティック
StringBuilder: 484 ティック
StringBuilder: 482 ティック
StringBuilder: 508 ティック
StringBuilder: 504 ティック
于 2008-09-22T14:56:33.987 に答える
0

実は、昨日これらのテストを実行しましたが、遅くなっていたので回答を差し控えました。

要するに、両方とも平均して同じ時間がかかるようです。私は100000回以上の反復でテストを行いました。

StringBuilder も試してみます。家に帰ったら、コードと結果を投稿します。

于 2008-08-20T13:43:31.030 に答える