VB.NETなどの元となった言語であるBASICには、プリミティブ型として文字列型が存在していました。 この文字列型は他の言語にはない使いやすさがあり、多少の仕様変更を伴いながらもBASICからQucik BASIC、Visual Basicと変わることなく受け継がれてきました。 Visual Basic .NETおよびC#でももちろん文字列型を扱うことができますが、VBの文字列型と比較すると格段に機能が向上しています。 .NET Frameworkでは文字列に関する処理をまとめ直し、文字列型はStringクラスとして存在するようになり、様々な機能が追加されています。
Stringクラスの個々の機能を説明する前に、.NET FrameworkにおけるStringクラスの位置づけと挙動、言語との関わりについてざっと見ておきます。
文字列型とStringクラス
.NET Frameworkにおける文字列型では、System.Stringクラスでその機能が提供されます。 例えば文字列の長さを調べたり、連結や分割などの加工を行ったりする場合にはStringクラスのプロパティやメソッドを利用することになります。 (Len
やstrcat
のような個別の関数は使いません)
次のコードが示すように、C#の組み込み型であるstring
、VB.NETの組み込み型であるString
は、どちらも.NET FrameworkにおけるSystem.Stringクラスのエイリアス(別名)であるため、両者は全く同じ型となります。
したがって、string型/String型として宣言した変数と、System.Stringとして宣言した変数はどちらも同じ型となるため、相互に代入可能で、かつどちらも同じメソッド・プロパティを使用することができ、全く同じように扱うことができます。
各言語の組み込み型と.NET Frameworkの型との対応については型の種類・サイズ・精度・値域 §.基本的なデータ型と対応する各言語の型を参照してください。
静的メソッドを呼び出す場合も同様で、文字列型またはSystem.Stringクラスのメソッドとして呼び出しても全く同じ動作となります。
stringとString
VB.NETではSystem名前空間をインポートすればどちらもString
という表記になり組み込み型のString
とString
クラスとの区別が曖昧になります。
一方C#では、同じ文字列型でも組み込み型を表すstring
とSystem.Stringを表すString
の両方の表記を混在させることができます。
既に説明したようにstring
とString
のどちらを使っても同じですが、C#では一般に、変数や引数、メンバなどの宣言ではstring
を使い、静的メソッドを呼び出す場合などにはString
を使う、という使い分けをすることが多いようです。
逆に、次のような使い分けをすることもできます。 表記が異なるだけで上記のコードと以下のコードは全く等価です。
当然、string
やString
のどちらかだけに統一することもできますが、ガイドラインやコーディング規約などで定められている場合は、それに合わせて統一することが推奨されます。
インデックス
System.Stringクラスでは、インデックスは0から始まります(0-based)。 例えば"ABC"
という文字列の場合、A
のインデックスは0
になります(1
ではなく)。 つまり配列におけるインデックスと同様になります。 Stringクラスの文字列操作メソッドでは、配列同様にインデックスを0
から始まるものとして扱います。
インデックスの扱いは、C#やVBといった言語の違いに関わらず、.NET Frameworkですべて共通しています。 なお、Visual Basic 6までは文字列のインデックスは1から始まる(1-based)とされているため、Len
やInStr
といったVBの文字列関数を使ったコードを移植する場合は特に注意が必要です。
n文字目という表記とインデックスの対応について注意を要する場合があります。 例えば、1文字目という表記が文字列のインデックス0
を表す場合もあれば、文字の位置とインデックスを対応させるために0文字目と表記してインデックス0
を指す場合もあります。 一般には前者であることが多いようですが、ドキュメントや文脈によっては後者が用いられる場合もあります。
VB.NETでも引き続きLen
等のVB由来の文字列関数を使用し続けることはできます。 また、一般的には推奨されませんが、C#でもこれらの関数を使うことはできます。 詳しくはVBの文字列関数を参照してください。
参照型としての挙動
System.Stringはクラスであるため参照型になりますが、通常の参照型とは見かけ上の挙動が異なります。
s2にs1を代入した時点で両者は同じインスタンスを参照することになり、その後s1に"bar"
を代入すれば同じ参照となっているs2も"bar"
となる、という挙動を予想することもできますが、実際にはs2は"foo"
のままとなります。
このような結果となるのは、s1に"bar"
を代入している箇所で新しい文字列型のインスタンス"bar"
が生成され、それがs1に代入されているためです。 上記のコードが次のようなコードで動作しているととらえるとその挙動が理解しやすいかもしれません(擬似コードのため実際には動作しません)。
参照と等価演算子
C#において、文字列型同士の等価演算子==
、不等価演算子!=
による比較では、参照の比較ではなく文字列の等価性の比較が行われます。 つまり==
演算子では、両辺のインスタンスが異なっていても文字列として等しければ両辺は等しいものとして扱われます。
文字列の比較については、文字列の探索・比較 §.文字列の比較・等価性の検証で詳しく解説します。 参照の比較と値の比較の違いについては値型と参照型 §.同値性・同一性の比較を参照してください。
C#で文字列型同士の参照の比較(同一のインスタンスであるかどうかの比較)を行うには、いったんobject
にキャストして等価演算子==
で比較するか、Object.ReferenceEqualsメソッドを使います。
VB.NETで文字列型同士の参照の比較(同一のインスタンスであるかどうかの比較)を行うには、Is
演算子を使います。 Is
演算子では文字列の等価性の比較は行われません。
関係演算子
C#では、関係演算子(<
, >
, <=
, >=
)による文字列の大小関係の比較はサポートされていません。 これらを使った文字列の比較はコンパイルエラーとなります。
このようにC#では関係演算子による文字列の比較はできませんが、代わりにString.Compareメソッドを使うことによって文字列の大小関係を比較することが出来ます。 このことについては文字列の探索・比較 §.比較 (CompareTo, Equals, Compare)で詳しく解説します。
VBでは、関係演算子を用いて文字列同士の大小関係を比較することが可能です。