文字列を連結するには、連結演算子の + (VB.NETでは & でも可)を使います。
Dim s1 As String = "こんにちは。" Dim s2 As String = "さようなら。" '2つの文字列を連結する Dim s3 As String = s1 & s2 's3は"こんにちは。さようなら。"となる
string s1 = "こんにちは。"; string s2 = "さようなら。"; //2つの文字列を連結する string s3 = s1 + s2; //s3は"こんにちは。さようなら。"となる
補足:「"こんにちは。" + "さようなら。"」のように文字列リテラルを直接つなげると、コンパイラが自動的に「"こんにちは。さようなら。"」とするようです。
文字列を連結するメソッドとして、String.Concatメソッドがあります。String.Concatメソッドを使ったときと連結演算子を使ったときの違いは、全くありません。ビルドするとどちらもString.Concatが使われるようになります。
Concatメソッドにはパラメータに文字列を2つから4つ指定できるオーバーロードがあります。さらに、文字列の配列をパラメータに指定できるオーバーロードもあります。連結演算子で2~4の文字列を連結するときは前者を、5個以上の文字列を連結するときは後者を使用するようです。
Dim s1 As String = "こんにちは。" Dim s2 As String = "さようなら。" '2つの文字列を連結する Dim s3 As String = s1 & s2 'Concatを使っても全く同じ Dim s4 As String = String.Concat(s1, s2)
string s1 = "こんにちは。"; string s2 = "さようなら。"; //2つの文字列を連結する string s3 = s1 + s2; //Concatを使っても全く同じ string s4 = string.Concat(s1, s2);
VB.NETには、 + と & の2つの連結演算子があります。2つの文字列型(String型)を連結する場合は、どちらを使用しても同じです。ただし、片方(もしくは両方)が文字列型でない場合は、+ 演算子では文字列の連結とはならず、数値の足し算と判断されてしまうかもしれません(詳しくは、「+ 演算子 (Visual Basic)」)。よってMSDNでは、文字列の連結では + ではなく、 & を使うべきとされています。
StringBuilderクラスのAppendメソッドを使って、文字列を連結することもできます。1,2回文字列を連結する程度であれば連結演算子を使用した方がパフォーマンスが良いですが、例えばループを使って何回も文字列を追加していくような場合は、StringBuilderクラスを使用した方がパフォーマンスが向上します。詳しくは、「StringBuilderのパフォーマンス」をご覧ください。
Dim s1 As String = "こんにちは。" Dim s2 As String = "さようなら。" 'StringBuilder.Appendを使って、2つの文字列を連結する Dim sb As New System.Text.StringBuilder() sb.Append(s1) sb.Append(s2) Dim s3 As String = sb.ToString() 's3は"こんにちは。さようなら。"となる
string s1 = "こんにちは。"; string s2 = "さようなら。"; //StringBuilder.Appendを使って、2つの文字列を連結する System.Text.StringBuilder sb = new System.Text.StringBuilder(); sb.Append(s1); sb.Append(s2); string s3 = sb.ToString(); //s3は"こんにちは。さようなら。"となる
「連結」というより「1つにまとめる」という感じですが、String.Formatメソッドを使うこともできます。ただし、後述するパフォーマンスについての説明にあるように、String.Formatメソッドは他の方法と比べてパフォーマンスが劣ります。
Dim s1 As String = "こんにちは。" Dim s2 As String = "さようなら。" 'String.Formatを使って、2つの文字列を連結する Dim s3 As String = String.Format("{0}{1}", s1, s2) 's3は"こんにちは。さようなら。"となる
string s1 = "こんにちは。"; string s2 = "さようなら。"; //String.Formatを使って、2つの文字列を連結する string s3 = string.Format("{0}{1}", s1, s2); //s3は"こんにちは。さようなら。"となる
文字列の配列の要素を連結するには、String.Joinメソッドを使用します。String.Joinメソッドは、連結する要素と要素の間に入れる文字列(区切り記号)を指定することができます。また、連結する要素の範囲を指定することもできます。
文字列の配列を連結するには、String.Concatメソッドや、ループして連結演算子やStringBuilder.Appendなどを使う方法もありますが、「StringBuilder vs. String / Fast String Operations with .NET 2.0」によると、String.Joinメソッドを使う方法が一番速いそうです。
以下にString.Joinを使用した例を示します。
Dim strAry As String() = New String() {"今日", "は", "いい", "天気", "です", "。"} '区切り記号なしで、文字列の配列を連結する Dim s1 As String = String.Join("", strAry) '今日はいい天気です。 '区切り記号を"|"にして連結する Dim s2 As String = String.Join("|", strAry) '今日|は|いい|天気|です|。 '3番目から最後までの要素を連結する Dim s3 As String = String.Join("", strAry, 2, strAry.Length - 2) 'いい天気です。
string[] strAry = new string[] { "今日", "は", "いい", "天気", "です", "。" }; //区切り記号なしで、文字列の配列を連結する string s1 = string.Join("", strAry); //今日はいい天気です。 //区切り記号を"|"にして連結する string s2 = string.Join("|", strAry); //今日|は|いい|天気|です|。 //3番目から最後までの要素を連結する string s3 = string.Join("", strAry, 2, strAry.Length - 2); //いい天気です。
ここからは、複数の文字列を連結する時、どのようにすればパフォーマンスが向上するかについて説明します。
「C# String Concat Programs」によると、複数の文字列を連結する時、連結演算子やConcatメソッドを使って一度に連結する方法が、String.FormatやStringBuilder.Appendメソッドを使った方法よりもパフォーマンスが良いということです。
私も以下のようなコードで試してみましたが(.NET Framework 4.0)、確かに連結演算子で一度に連結する方法が一番速かったです。
Dim s1 As New String("あ"c, 10) Dim s2 As New String("い"c, 10) Dim s3 As New String("う"c, 10) Dim s4 As New String("え"c, 10) '連結演算子で連結する Dim sw1 As New System.Diagnostics.Stopwatch() sw1.Start() For i As Integer = 0 To 10000000 Dim r1 As String = s1 & s2 & s3 & s4 Next sw1.Stop() Console.WriteLine(sw1.ElapsedTicks) '1863170 'String.Formatで連結する Dim sw2 As New System.Diagnostics.Stopwatch() sw2.Start() For i As Integer = 0 To 10000000 Dim r2 As String = String.Format("{0}{1}{2}{3}", s1, s2, s3, s4) Next sw2.Stop() Console.WriteLine(sw2.ElapsedTicks) '8028348 'StringBuilder.Appendで連結する Dim sw3 As New System.Diagnostics.Stopwatch() sw3.Start() For i As Integer = 0 To 10000000 Dim sb As New System.Text.StringBuilder() sb.Append(s1).Append(s2).Append(s3).Append(s4) Dim r3 As String = sb.ToString() Next sw3.Stop() Console.WriteLine(sw3.ElapsedTicks) '5184637
string s1 = new string('あ', 10); string s2 = new string('い', 10); string s3 = new string('う', 10); string s4 = new string('え', 10); //連結演算子で連結する System.Diagnostics.Stopwatch sw1 = new System.Diagnostics.Stopwatch(); sw1.Start(); for (int i = 0; i < 10000000; i++) { string r1 = s1 + s2 + s3 + s4; } sw1.Stop(); Console.WriteLine(sw1.ElapsedTicks); //1863170 //String.Formatで連結する System.Diagnostics.Stopwatch sw2 = new System.Diagnostics.Stopwatch(); sw2.Start(); for (int i = 0; i < 10000000; i++) { string r2 = string.Format("{0}{1}{2}{3}", s1, s2, s3, s4); } sw2.Stop(); Console.WriteLine(sw2.ElapsedTicks); //8028348 //StringBuilder.Appendで連結する System.Diagnostics.Stopwatch sw3 = new System.Diagnostics.Stopwatch(); sw3.Start(); for (int i = 0; i < 10000000; i++) { System.Text.StringBuilder sb = new System.Text.StringBuilder(); sb.Append(s1).Append(s2).Append(s3).Append(s4); string r3 = sb.ToString(); } sw3.Stop(); Console.WriteLine(sw3.ElapsedTicks); //5184637
ただし、一度に連結するのではなく、例えばループを使って次々と文字列を追加していくようなケースでは、StringBuilderのパフォーマンスが優れています。詳しくは、「StringBuilderのパフォーマンス」で説明しています。
ここからは、あまり役に立たない余談です。
同じく「C# String Concat Programs」によると、さらに面白いことに、5つの文字列を連結する場合は、一度に連結するよりも、4つの文字列を連結させてから残りの文字列を連結させた方が高速だということです。つまり、Concatメソッドの文字列の配列をパラメータとするオーバーロードは、それ以外のオーバーロードと比べてパフォーマンスが大きく劣るということです。
私も実際に以下のようなコードで試してみましたが、確かに2回に分けた方が速かったです。また、5つの文字列を4と1に分けるよりも、3と2に分けた方が若干速かったです。
Dim s1 As New String("あ"c, 10) Dim s2 As New String("い"c, 10) Dim s3 As New String("う"c, 10) Dim s4 As New String("え"c, 10) Dim s5 As New String("お"c, 10) '一度に連結する Dim sw1 As New System.Diagnostics.Stopwatch() sw1.Start() For i As Integer = 0 To 50000000 Dim r1 As String = s1 & s2 & s3 & s4 & s5 Next sw1.Stop() Console.WriteLine(sw1.ElapsedTicks) '21527242 '2回に分けて連結する(4,1に分ける) Dim sw2 As New System.Diagnostics.Stopwatch() sw2.Start() For i As Integer = 0 To 50000000 Dim r2 As String = s1 & s2 & s3 & s4 r2 += s5 Next sw2.Stop() Console.WriteLine(sw2.ElapsedTicks) '14886505 '2回に分けて連結する(3,2に分ける) Dim sw3 As New System.Diagnostics.Stopwatch() sw3.Start() For i As Integer = 0 To 50000000 Dim r3 As String = s1 & s2 & s3 r3 += s4 & s5 Next sw3.Stop() Console.WriteLine(sw3.ElapsedTicks) '13423224
string s1 = new string('あ', 10); string s2 = new string('い', 10); string s3 = new string('う', 10); string s4 = new string('え', 10); string s5 = new string('お', 10); //一度に連結する System.Diagnostics.Stopwatch sw1 = new System.Diagnostics.Stopwatch(); sw1.Start(); for (int i = 0; i < 50000000; i++) { string r1 = s1 + s2 + s3 + s4 + s5; } sw1.Stop(); Console.WriteLine(sw1.ElapsedTicks); //21527242 //2回に分けて連結する(4,1に分ける) System.Diagnostics.Stopwatch sw2 = new System.Diagnostics.Stopwatch(); sw2.Start(); for (int i = 0; i < 50000000; i++) { string r2 = s1 + s2 + s3 + s4; r2 += s5; } sw2.Stop(); Console.WriteLine(sw2.ElapsedTicks); //14886505 //2回に分けて連結する(3,2に分ける) System.Diagnostics.Stopwatch sw3 = new System.Diagnostics.Stopwatch(); sw3.Start(); for (int i = 0; i < 50000000; i++) { string r3 = s1 + s2 + s3; r3 += s4 + s5; } sw3.Stop(); Console.WriteLine(sw3.ElapsedTicks); //13423224
ある程度の数の文字列ならば、一度に連結するよりも分けて連結した方が速くなることは分かりましたが、数が多くなれば一度に連結した方が速くなるはずです。そこで、幾つ連結すれば一度に連結した方が速くなるか調べてみました。すると、私の環境では(.NET Framework 4.0)、大体14個以上の文字列を連結した時、一度に連結した方が速くなりました。
Dim s1 As New String("あ"c, 10) Dim s2 As New String("い"c, 10) Dim s3 As New String("う"c, 10) Dim s4 As New String("え"c, 10) Dim s5 As New String("お"c, 10) Dim sw1 As New System.Diagnostics.Stopwatch() sw1.Start() For i As Integer = 0 To 50000000 Dim r1 As String = s1 & s2 & s3 & s4 & s5 & s1 & s2 & s3 & s4 & s5 _ & s1 & s2 & s3 & s4 Next sw1.Stop() Console.WriteLine(sw1.ElapsedTicks) '52284326 Dim sw2 As New System.Diagnostics.Stopwatch() sw2.Start() For i As Integer = 0 To 50000000 Dim r2 As String = s1 & s2 & s3 & s4 r2 += s5 & s1 & s2 r2 += s3 & s4 & s5 r2 += s1 & s2 & s3 r2 += s4 Next sw2.Stop() Console.WriteLine(sw2.ElapsedTicks) '53227035
string s1 = new string('あ', 10); string s2 = new string('い', 10); string s3 = new string('う', 10); string s4 = new string('え', 10); string s5 = new string('お', 10); System.Diagnostics.Stopwatch sw1 = new System.Diagnostics.Stopwatch(); sw1.Start(); for (int i = 0; i < 50000000; i++) { string r1 = s1 + s2 + s3 + s4 + s5 + s1 + s2 + s3 + s4 + s5 + s1 + s2 + s3 + s4; } sw1.Stop(); Console.WriteLine(sw1.ElapsedTicks); //52284326 System.Diagnostics.Stopwatch sw2 = new System.Diagnostics.Stopwatch(); sw2.Start(); for (int i = 0; i < 50000000; i++) { string r2 = s1 + s2 + s3 + s4; r2 += s5 + s1 + s2; r2 += s3 + s4 + s5; r2 += s1 + s2 + s3; r2 += s4; } sw2.Stop(); Console.WriteLine(sw2.ElapsedTicks); //53227035
なお、環境によって結果が変わる可能性があることをご了承ください。
注意:この記事では、基本的な事柄の説明が省略されているかもしれません。初心者の方は、特に以下の点にご注意ください。