C#で文字列変数と整数変数を連結するときに.ToString()を使用する必要がありますか?


19
int a = 1;
int b = 2;
int sum = a + b;
string expression = "Expression: " + a + " + " + b + " = " + sum;
Console.WriteLine(expression); //displays Expression 1 + 2 = 3

使用する必要があります:

string expression = "Expression: " + a + " + " + b + " = " + sum;

または

string expression = "Expression: " + a.ToString() + " + " + b.ToString() + " = " + result.ToString();

andをToString()連結するときに使用することをお勧めしますか?stringint


6
ではa + "" + b + ""または"" + a + b + ""、それは問題ではありません:それは、すべての文字列の連結です。でa + b + ""、それは問題ありません:ab最初に追加されます。
ティムS. 14

4
サイドノート:ではVB.NET、この曖昧さは、明示的に持つことによって回避される文字列連結演算子を"Expression: " + a(オプション厳密に付き)コンパイル時にエラーがスローされます"Expression: " & a文字列の連結を実行します。
ハインジ

最初のコードではボクシング(intからInt32)が行われますが、2番目のコードでは行われません。2番目の方が明らかに高速です。
ランダムなアルファベット

回答:


33

ToString 使用法

いいえ、ToStringここでは使用しないでください。

文字列の連結は、非文字列を自動的に文字列に変換します。つまり、2つのバリアントはほぼ同一です。

一方または両方のオペランドが文字列型の場合、事前定義された加算演算子は、オペランドの文字列表現を連結します。

ソース:C#言語仕様:加算演算子、MSDN

一方、最初のもの(なしToString):

  • 書くのが短い
  • 読むのが短い
  • 保守が簡単で、次のとおりです。
  • 文字列を連結するという著者の意図を正確に示しています。

だから、最初のものを好む。

フードの下

また興味深いのは、内部で何が起こるかを確認することです。確認する方法の1つは、LINQPad内でILコードを監視することです。このプログラム:

void Main()
{
    var a = 3;
    var b = " Hello";
    var c = a + b;
    Console.WriteLine(c);
}

次のILに変換されます。

IL_0001:  ldc.i4.3    
IL_0002:  stloc.0     // a
IL_0003:  ldstr       " Hello"
IL_0008:  stloc.1     // b
IL_0009:  ldloc.0     // a
IL_000A:  box         System.Int32
IL_000F:  ldloc.1     // b
IL_0010:  call        System.String.Concat
IL_0015:  stloc.2     // c
IL_0016:  ldloc.2     // c
IL_0017:  call        System.Console.WriteLine

あれSystem.String.Concat?つまり、元のコードも同様に記述でき、まったく同じILに変換されます。

void Main()
{
    var a = 3;
    var b = " Hello";
    var c = string.Concat(a, b); // This is the line which was changed.
    Console.WriteLine(c);
}

のドキュメントstring.Concat(object[])を読む、次のことを学ぶことができます。

メソッドは、そのオブジェクトのパラメーターなしメソッドを呼び出すことにより、args内の各オブジェクトを連結ToStringします。区切り文字は追加されません。

これToStringは冗長であることを意味します。また:

String.Empty 配列内のnullオブジェクトの代わりに使用されます。

これは、オペランドの一部がヌルであるケースをうまく処理します(脚注1を参照)。

最後の例では、連結がに変換されましたがstring.Concat、コンパイラーの最適化も強調する必要があります。

var a = "Hello " + "World";

に翻訳されます:

ldstr       "Hello World"
stloc.0

一方:

var a = string.Concat("Hello ", "World");

に翻訳されます:

ldstr       "Hello "
ldstr       "World"
call        System.String.Concat
stloc.0

その他の選択肢

もちろん、C#でオブジェクトの文字列表現を連結する他の方法があります。

  1. StringBuilder多くの連結操作を行う必要がある場合に使用され、作成される中間文字列の数を減らすのに役立ちます。StringBuilder連結を使用するか通常の連結を使用するかを決定するのは簡単ではありません。プロファイラーを使用するか、Stack Overflowで関連する回答を検索します。

    を使用StringBuilderすると、コードの読み取りと保守が難しくなるという大きな欠点があります。あなたの質問のような単純なケースStringBuilderでは、コードの可読性に有害であるだけでなく、パフォーマンスの面でも役に立ちません。

  2. string.Join 区切り文字を追加する必要がある場合に使用する必要があります。

    明らかに、string.Join文字列を連結するために空の区切り文字と共に使用しないでください。

  3. string.Format文字列の連結よりも文字列テンプレートが望ましい場合に使用できます。あなたがそれを好むかもしれないケースの1つは、kunthetによる答えで示唆されているように、メッセージがローカライズされるときです。

    使用にstring.Formatはいくつかの欠点があり、あなたのような単純な場合には不向きです:

    • 単純な「{0}」プレースホルダーでは、どのパラメーターがどこに行くのかが不明確なことがよくあります。誤ってパラメーターを逆にしたり、忘れたりすることがよくあります。幸いなことに、C#6ではこの問題を解決する文字列補間がついに導入されました

    • ランタイムのパフォーマンスが低下する場合があります。もちろん、想定していないstring.Formatです常に遅くなります。パフォーマンスが重要な場合は、2つのアプローチを測定し、仮定ではなく実際の結果に基づいてどちらが速いかを判断します。

    • コードは書くのが少し長く、読むのが長く、維持するのが難しいですが、これは非常にマイナーであり、あまり気にする必要はありません。


¹オブジェクトの1つがである場合に違いが現れますnull。がなければToString、a nullは空の文字列に置き換えられます。ではToString、a NullReferenceExceptionがスローされます。


1
まさにこの理由(予測不可能な動作)のため+、ほとんどの言語では、文字列とを連結することは悪い習慣と見なされます。この場合、を使用しますstring.Concatが、多くの場合string.Formatはより良いです。これは、使用に確かにPython的ではない+、とPEP 3101以来%の賛成で十分として推奨されてstr.format
アルダシー

2
null本当に「うまく処理する」ために空の文字列を置き換えていますか?まあ、それは...「次のエラー履歴書上の」悪いようではありません
デュプリケータ

内部で、.ToString()を呼び出さずに連結すると、ボクシングが発生し、...のConcat(object[])代わりに使用されますConcat(string[])。だから"string " + i実際には同一ではない"string " + i.ToString()
ランダムアルファベット

@RandomAlphabets:有効なポイント。ただし、違いは単に、ある場所ではToString()OPのコードSystem.String.Concat、別の場合ではの実装の場所です。したがって、答えは有効です。利益のないコードを書かないでください。
アルセニMourzenko

15

代わりに、文字列フォーマッタを使用する必要があります。数値を文字列表現またはローカライズにフォーマットする方が簡単です。例えば:

string expression = string.Format("Expression: {0} + {1} = {2}", a, b, sum);

MSDNの詳細情報。

ただし、文字列のフォーマッタは文字列の連結よりも読みにくくなります(パフォーマンスも低下する可能性があります)。


6
このオプションが優れている理由を説明することに注意してください。
世界エンジニア14

@WorldEngineer:説明を更新しました。
kunthet 14

12
他の人については知りませんが、実際にはこれがより読みやすいと思います。おそらく、私はs [n] printfがこの種のコードの唯一の現実的なオプションであるCで育ったからでしょう。
ジュール14

2
しかし、この方法では、1つではなく3つの間違いの原因がわかります。文字列に何かを追加するときは、1)書式文字列を変更する必要があります。2)リストに新しいパラメーターを追加することを忘れないでください。3)新しいパラメーターを配置するリスト内の正しい場所を選択してください。
ルスラン

2
チャイムを鳴らして、C#6の文字列補間機能についてお知らせします。同じ結果を得るには、「Expression:\ {a} + \ {b} = \ {sum}」と記述します。codeproject.com/Articles/846566/...
cwap

-2

+連結を使用する場合、それ自体がString.Concatメソッドを使用します。文字列自体は+演算子を公開しません。

例えば:

int i = 10;
string str = "hello" + i;

にコンパイルされます:

int i = 10;
object o1 = "hello";
object o2 = i; // Note boxing
string str = string.Concat(o1, o2);

を直接呼び出す場合ToString、ボクシングを回避し、Concat(string, string)オーバーロードを呼び出します。したがって、ToString呼び出しは十分に重要ではありませんが、少し効率的です。読みやすいと感じる例の方が良いでしょう。


2
これは単に繰り返しポイントがで作られたと説明しているようだ前の答え:「文字列の連結に自動的に変換非文字列の文字列の中に...」
ブヨ
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.