どう使い分ける? 文字列の連結方法

2010年8月5日公開

プログラミングにおいて文字列の連結は頻繁に行われる基本的な処理のひとつですが、その記述方法にはいくつかの種類があります。それぞれの記述方法にはそれぞれの特性があり、利用目的に応じて適切に使い分けることでプログラムの品質が向上し信頼性の高いシステム開発につながります。

そこで、このコラムでは .NETのVisual BasicとC#を例にとり、文字列連結の記述方法とそれぞれの特性を解説していきます。

写真「八巻 雄哉」

グレープシティ テクニカルエバンジェリスト
八巻 雄哉

2003年1月入社。PowerToolsシリーズのテクニカルサポートを担当するかたわら、製品開発やマーケティングにも従事。2006年から、.NETテクノロジーとPowerToolsシリーズ普及のためエバンジェリストとして活動中。
Microsoft MVP for Development Platforms -Client App Dev Jan 2009 -Dec 2012

+と&はどっちがよい?

Visual Basicでは、文字列連結に使える演算子として+演算子と&演算子の2つが存在します。文字列連結ということに限ればどちらの演算子も同じように使えますが、2つの演算子には決定的な違いがあります。それは、+演算子が数値加算と文字列連結の両方で使用できるのに対し、&演算子は文字列連結にしか使用できないという点です。

この違いは以下のようなコードで確認することができます。

Dim group As String = "1976"
Dim number As Integer = 48
Dim id1 As String = Group + Number
Dim id2 As String = Group & Number

Console.WriteLine("ID1={0}", id1)
Console.WriteLine("ID2={0}", id2)
Console.ReadKey()

実行結果 :

Id1=2024
Id2=197648

Option StrictステートメントがOnの場合、上記の+演算子部分のコードはコンパイルエラーとなります。

一方が数値でもう一方が文字列の場合、+演算子を使うと文字列が数値型(Double)に変換され加算の処理が行われます。

MSDNライブラリの「+ 演算子 (Visual Basic)」には下記のような記載があります。

+ 演算子を使用すると、加算と文字列連結のどちらが行われるのか、事前にはわかりにくい場合があります。連結に & 演算子を使用することで、あいまいさがなくなり、プログラムの可読性が向上します。

これらのことから、Visual Basicで文字列連結を行う場合には、+演算子ではなく&演算子を使うべきと言えるでしょう。

String.Concatメソッド

+演算子や&演算子を使った文字列連結は、コンパイル時にString.Concatメソッドのいずれかのオーバーロードの呼び出しに置き換えられます。そのため、記述文字数が多くなるString.Concatメソッドをあえて使用する必要はあまりないでしょう。

文字列連結のパフォーマンス

.NETのStringデータ型は、インスタンス作成時以外に値を変更できない不変型です。文字列連結を含む値の変更は、実際には値が変更されているのではなく都度新しいインスタンスが生成されています。そのため、+演算子や&演算子を使って文字列連結を繰り返した場合、そのメモリ割り当てのコストから期待するパフォーマンスを得られないことがあります。

そのような場合に有効とされているのがStringBuilderクラスです。StringBuilderクラスは必要に応じてバッファサイズを拡大させて値の変更ができる可変型となっており、Appendメソッドを使って文字列の連結を行うことでメモリ領域の確保を最小限に抑えることができます。

このことはマイクロソフト社のサイトに限らず様々なサイトで取り上げられているため、ご存知の方も多いのではないかと思います。

どんなときにStringBuilderを使ったらよいの?

しかしながら、どんな場合でも+演算子や&演算子に比べてStringBuilderがパフォーマンス上有利というわけではありません。

+演算子や&演算子を使った場合でも、下記のように文字列定数を1ステートメントで連結させていればコンパイル時に文字列定数がひとまとめにされるため実行時に連結処理は発生しません。

Dim sql = "SELECT Column1, Column2, Column3" _
          & " FROM Table1" _
          & " WHERE Column1 = @Column1"

つまり、下記のコードと等価になります。

Dim sql = "SELECT Column1, Column2, Column3 FROM Table1 WHERE Column1 = @Column1"

また、定数ではなく変数であっても1ステートメント内の連結であれば、3つの場合にはString.Concat (String, String, String)、4つの場合にはString.Concat (String, String, String, String)、5つ以上の場合にはString.Concat (String[])の呼び出しに置き換えられるようになっているため、StringBuilder.Appendメソッドと比較してもパフォーマンス上大きく劣ることはありません。

プログラミングにおいてパフォーマンスを意識することは大切なことですが、コードの可読性や記述のしやすさもまた重要な要素であることに異論はないでしょう。単純に考えても、1文字の+演算子や&演算子に対してStringBuilder.Appendメソッドは“sb.Append()”と書いても11文字記述する必要があります。

個人的な見解となりますが、ループ処理を使って動的な文字列連結を繰り返す場合にはStringBuilderクラスを、それ以外の場合には+演算子や&演算子を使うとよいのではないでしょうか。

開発者はどう使い分けている?

2010年7月22日に配信したPowerNews 308号で今回のコラムで解説した「+演算子」「&算子」「String.Concatメソッド」「StirngBuilder.Appendメソッド」を開発者の皆さんが、どのように使っているのかアンケートを行いました。以下に回答結果と皆さまからいただいたコメントを紹介します。

質問内容

普段、文字列を連結する際にどのようなコードを書きますか?

  • & 演算子
  • + 演算子
  • String.Concatメソッド
  • StringBuilder.Appendメソッド

回答結果

有効回答数:50
アンケート実施日:2010/7/22
普段、文字列を連結する際にどのようなコードを書きますか? 比率
& 演算子 48%
+ 演算子 16%
& 演算子, + 演算子 4%
& 演算子, StringBuilder.Appendメソッド 4%
+ 演算子, StringBuilder.Appendメソッド 10%
& 演算子, + 演算子, StringBuilder.Appendメソッド 4%
StringBuilder.Appendメソッド 10%
String.Concatメソッド 2%
String.Concatメソッド, StringBuilder.Appendメソッド 2%
総計 100%
グラフ「PN308アンケート結果」

皆さんからいただいたコメント

+は演算される可能性があり、文字列結合には&が良いと聞きました。
&の方が1文字で済むから楽ですし、よほど速度の求められる場面でなければStringBuilderは使いません。いずれ変えていかなければならないんでしょうが…。
+演算子は、文字列連結というより、やはり数学の足し算のイメージがあるので、ほとんど使いません。他の人が+を使っていたら、変えてしまいます。
&演算子しか使用したことがありません。
他の方式を知る必要も無かったので、+演算子以外ははじめて知りました。
LotusNotesとか、いろいろやってると混乱してきます…記号は。
以前から&演算子を使っていたから。
また+演算子は文字列結合でなく数値の加算になってしまいそうだから怖い。
やっぱり&です。なんとStringBuilder.Appendだと20文字。
単純に&の20倍の工数がかかります。この差は大きいです。
どうしてもString.ConcatやStringBuilder.Appendに馴染めない…。
+だと足しちゃいそうで嫌です。
昔からの癖で、Access VBA では&、 .Net では、短い文字列の連結では+、SQL文など非常に長い文字列では、StringBuilder.Appendを使用しています。
パフォーマンスが必要とする繰り返しが少ない場面(SQL文の作成)では&演算子。パフォーマンスを必要とする繰り返しが多い場面(CSVファイル作成)では、StringBuilder.Appendメソッドを使用しています。
時と場合ですが、パフォーマンス重視ならStringBuilderでしょ。という感じです。
+演算子。誰でもわかる。可読性が高い。
+以外のコーディング方法を思いつかなかった自身に、かなりの冷や汗…。
考えながらコーディングしているときには、+演算子しかない。
読みやすい、分かりやすいがイチバン
ループなどの速度が気になる箇所のみStringBuffer.Appendを使用。
(しかし時間計測していないので、案外+演算子でも十分かも知れない)
短い演算は+、SQL文を生成する時など、長い文字列連結時はStringBuilder.Appendを使用します。
連結回数が少ない場合は"+"、ループなどで連結する場合はStringBuilderを使います。"+"の方がStringBuiliderに比べてコストが高いそうですが、コードは読みやすいですので、使い分けてます。
結合する文字列の量で、少ないときは +演算子、多いときはStringBuilderと使い分けています。
単純な結合なら+、ループして結合するようなのはStringBuilder、中間はstring.Formatって感じです。
答えで最も多いのではないかと思う strcat()。僕は sprintf()の方がよく使う。組み込みとかのバッファが固定長でやばい時は、自作関数。C#でも Formatは多用しますね。パフォーマンスは落ちるだろうけど、多国語対応とかでは必要になると思う。
御社にサポートで質問した際、String.Concatを教えてもらいました。
どれが一番良いのでしょうか?
SQL文のように長くなる場合は、StringBuilder。
短い連結はString.Concatまたは、String.Formatを使ってます。
4つ以上の連結になりそうなら、StringBuilderのAppendメソッドを使いますが、それ以下の場合は、手を抜いて+演算子で。
String.Concat 知らなかったです(^^;)。
コーディング上1行に収まる場合は + 演算子。コード自体が1行で収まらない場合は StringBuilder を使っています。2:8ぐらいかな…。

関連記事

  1. » 戻り値の指定、VBとVB.NETでどう違う?
  2. » どう使い分ける?値渡しと参照渡し