2016-01-08T23:53:51の更新内容

programming/netfx/string/0_abstract/index.wiki.txt

current previous
11,52 11,9
 
#adunit
#adunit
 

        

        
 
*文字列型とStringクラス [#StringClass]
*文字列型とStringクラス [#StringClass]
~
.NET Frameworkにおける文字列型では、&msdn(netfx,type,System.String){System.Stringクラス};でその機能が提供されます。 例えば文字列の長さを調べたり、連結や分割などの加工を行ったりする場合にはStringクラスのプロパティやメソッドを利用することになります。 (``Len``や``strcat``のような個別の関数は使いません)
次のコードが示すように、C#のstring型、VB.NETのString型は、.NET Frameworkにおける&msdn(netfx,type,System.String){System.Stringクラス};のエイリアス(別名)で、両者は全く同じものです。
 

        

        
~
#tabpage(codelang=cs,container-title=文字列操作の例)
#tabpage(codelang=cs)
+
#code{{
+
using System;
+

          
+
class Sample
+
{
+
  static void Main()
+
  {
+
    string s = "foobarbaz";
+

          
+
    // 文字列sの長さを表示する
+
    Console.WriteLine(s.Length);
+

          
+
    // 文字列sの6文字目から3文字分を切り出して表示する
+
    Console.WriteLine(s.Substring(6, 3));
+
  }
+
}
+
}}
+
#tabpage(codelang=vb)
+
#code{{
+
Imports System
+

          
+
Class Sample
+
  Shared Sub Main()
+
    Dim s As String = "foobarbaz"
+

          
+
    ' 文字列sの長さを表示する
+
    Console.WriteLine(s.Length)
+

          
+
    ' 文字列sの6文字目から3文字分を切り出して表示する
+
    Console.WriteLine(s.Substring(6, 3))
+
  End Sub
+
End Class
+
}}
+
#tabpage-end
+

          
+
#prompt(実行結果){{
+
9
+
baz
+
}}
+

          
+
次のコードが示すように、C#の組み込み型である``string``、VB.NETの組み込み型である``String``は、どちらも.NET FrameworkにおけるSystem.Stringクラスのエイリアス(別名)で、両者は全く同じものです。
+

          
+
#tabpage(codelang=cs,container-title=組み込み文字列型とSystem.String)
 
#code{{
#code{{
 
using System;
using System;
 

        

        
100,109 57,6
 
baz System.String
baz System.String
 
}}
}}
 

        

        
+
したがって、string型/String型として宣言した変数と、System.Stringとして宣言した変数はどちらも同じ型となり、相互に代入可能で、いずれも同じように扱うことができます。
+

          
+
#remarks
+
各言語の組み込み型と.NET Frameworkの型との対応については[[programming/netfx/basic_types/0_characteristics#BasicTypes]]を参照してください。
+
#remarks-end
+

          
+
同様に、文字列型のメソッドを呼び出す際にSystem.Stringクラスのメソッドとして呼び出しても全く同じ動作となります。
+

          
+
#tabpage(codelang=cs,container-title=文字列型のメソッド呼び出し)
+
#code{{
+
using System;
+

          
+
class Sample
+
{
+
  static void Main()
+
  {
+
    string s1 = "foo";
+
    string s2 = "bar";
+

          
+
    // Equalsメソッドを使って2つの文字列が等しいか比べる
+
    bool b1 = string.Equals(s1, s2);
+
    bool b2 = System.String.Equals(s1, s2);
+

          
+
    Console.WriteLine(b1);
+
    Console.WriteLine(b2);
+
  }
+
}
+
}}
+
#tabpage(codelang=vb)
+
#code{{
+
Imports System
+

          
+
Class Sample
+
  Shared Sub Main()
+
    Dim s1 As String = "foo"
+
    Dim s2 As String = "bar"
+

          
+
    ' Equalsメソッドを使って2つの文字列が等しいか比べる
+
    Dim b1 As Boolean = String.Equals(s1, s2)
+
    Dim b2 As Boolean = System.String.Equals(s1, s2)
+

          
+
    Console.WriteLine(b1)
+
    Console.WriteLine(b2)
+
  End Sub
+
End Class
+
}}
+
#tabpage-end
+

          
+
#prompt(実行結果){{
+
False
+
False
+
}}
+

          
+
**stringとString
+
VB.NETではSystem名前空間をインポートすればどちらも``String``という表記になり組み込み型の``String``と``String``クラスとの区別が曖昧になります。
+

          
+
一方C#では、同じ文字列型でも組み込み型を表す``string``とSystem.Stringを表す``String``の両方の表記を混在させることができます。
+

          
+
既に説明したように``string``と``String``のどちらを使っても同じですが、C#では一般に、変数や引数、メンバなどの宣言では``string``を使い、静的メソッドを呼び出す場合などには``String``を使う、という使い分けをすることが多いようです。
+

          
+
#code(cs,比較的よく見られるstringとStringの使い分け){{
+
using System;
+

          
+
class Sample
+
{
+
  static void Main()
+
  {
+
    // 変数の宣言ではstringを使う
+
    string s1 = "foo";
+
    string s2 = "bar";
+

          
+
    // 静的メソッドの呼び出しではStringを使う
+
    bool b1 = String.Equals(s1, s2);
+

          
+
    Console.WriteLine(b1);
+
  }
+
}
+
}}
+

          
+
逆に、次のような使い分けをすることもできます。 表記が異なるだけで上記のコードと以下のコードは全く等価です。
+

          
+
#code(cs,上記の例とは異なるstringとStringの使い分け){{
+
using System;
+

          
+
class Sample
+
{
+
  static void Main()
+
  {
+
    // 変数の宣言ではStringを使う
+
    String s1 = "foo";
+
    String s2 = "bar";
+

          
+
    // 静的メソッドの呼び出しではstringを使う
+
    bool b1 = string.Equals(s1, s2);
+

          
+
    Console.WriteLine(b1);
+
  }
+
}
+
}}
+

          
+
当然、``string``や``String``のどちらかだけに統一することもできますが、ガイドラインやコーディング規約などで定められている場合は、それに合わせて統一することが推奨されます。
+

          
+

          
 
*参照型としての挙動 [#Assignment]
*参照型としての挙動 [#Assignment]
 
System.Stringはクラスであるため[[参照型>programming/netfx/valuetype_referencetype]]になりますが、通常の参照型とは見かけ上の挙動が異なります。
System.Stringはクラスであるため[[参照型>programming/netfx/valuetype_referencetype]]になりますが、通常の参照型とは見かけ上の挙動が異なります。
 

        

        
249,9 103,7
 
bar foo
bar foo
 
}}
}}
 

        

        
~
&var{s2};に&var{s1};を代入した時点で両者は同じインスタンスを参照することになり、その後&var{s1};に``"bar"``を代入すれば同じ参照となっている&var{s2};も``"bar"``となる、という挙動を予想することもできますが、実際には&var{s2};は``"foo"``のままとなります。
これは、s1に"bar"を代入している箇所で、新しい文字列型のインスタンス"bar"が生成され、それがs1に代入されているためです。 上のコードは、実際には次のようなコードで動いているととらえるとわかりやすいかもしれません(擬似コードのため実際には動作しません)。
+

          
+
このような結果となるのは、&var{s1};に``"bar"``を代入している箇所で''新しい文字列型のインスタンス``"bar"``''が生成され、それが&var{s1};に代入されているためです。 上記のコードが次のようなコードで動作しているととらえるとその挙動が理解しやすいかもしれません(擬似コードのため実際には動作しません)。
 

        

        
 
#tabpage(codelang=cs)
#tabpage(codelang=cs)
 
#code{{
#code{{
292,7 144,7
 
#tabpage-end
#tabpage-end
 

        

        
 
*参照と等価演算子 [#CompareReferenceAndEquality]
*参照と等価演算子 [#CompareReferenceAndEquality]
~
C#において、文字列型同士の等価演算子``==``、不等価演算子``!=``による比較では、参照の比較ではなく文字列の等価性の比較が行われます。 つまり``==``演算子では、両辺のインスタンスが異なっていても文字列として等しければ''両辺は等しい''ものとして扱われます。
C#では、文字列型同士の等価演算子==、不等価演算子!=による比較は、参照の比較ではなく文字列の等価性の比較が行われます。
 

        

        
 
#code(cs){{
#code(cs){{
 
using System;
using System;
318,7 170,7
 
True
True
 
}}
}}
 

        

        
~
C#で文字列型同士の参照の比較(同一のインスタンスであるかどうかの比較)を行うには、いったん``object``にキャストして等価演算子``==``で比較するか、&msdn(netfx,member,System.Object.ReferenceEquals){Object.ReferenceEqualsメソッド};を使います。
C#で文字列型同士の参照の比較を行うには、いったんobjectにキャストして等価演算子==で比較するか、&msdn(netfx,member,System.Object.ReferenceEquals){Object.ReferenceEqualsメソッド};を使います。
 

        

        
 
#code(cs){{
#code(cs){{
 
using System;
using System;
348,7 200,7
 
True
True
 
}}
}}
 

        

        
~
VB.NETにおいては、``Is``演算子による文字列同士の比較では参照の比較が行われます。 文字列の等価性の比較は行われません。
VB.NETでは、文字列同士のIs演算子による比較は参照の比較が行われます。 文字列の等価性の比較は行われません。
 

        

        
 
#code(vb){{
#code(vb){{
 
Imports System
Imports System
375,11 227,11
 
}}
}}
 

        

        
 
#remarks
#remarks
~
文字列の比較については、[[programming/netfx/string/2_1_comparison#string_comparison]]で詳しく解説します。 参照の比較と値の比較の違いについては[[programming/netfx/valuetype_referencetype#equality]]を参照してください。
文字列の比較については、[[programming/netfx/string/2_1_comparison]]で詳しく解説します。 参照の比較・値の比較の違いについては[[programming/netfx/valuetype_referencetype#equality]]を参照してください。
 
#remarks
#remarks
 

        

        
 
*関係演算子 [#RelationalOperator]
*関係演算子 [#RelationalOperator]
~
C#では、関係演算子(``<``, ``>``, ``<=``, ``>=``)による文字列の比較はサポートされていません。 これらを使った文字列の比較はコンパイルエラーとなります。
C#では、関係演算子(<, >, <=, >=)による文字列の比較はサポートされていません。 これらはコンパイルエラーとなります。
 

        

        
 
#code(cs){{
#code(cs){{
 
using System;
using System;
400,10 252,6
 
}
}
 
}}
}}
 

        

        
+
#remarks
+
このようにC#では関係演算子による文字列の比較はできませんが、代わりに&msdn(netfx,member,System.String.Compare){String.Compareメソッド};を使うことによって文字列の大小関係を比較することが出来ます。 このことについては[[programming/netfx/string/2_1_comparison#String.CompareTo]]で詳しく解説します。
+
#remarks-end
+

          
 
VBでは、関係演算子を用いて文字列同士を比較することが可能です。
VBでは、関係演算子を用いて文字列同士を比較することが可能です。
 
#code(vb){{
#code(vb){{
 
Imports System
Imports System
428,5 276,9
 
str1 > str2
str1 > str2
 
}}
}}
 

        

        
-
#remarks
-
C#では関係演算子による文字列の比較はできませんが、代わりに&msdn(netfx,member,System.String.Compare){String.Compareメソッド};を使うことで文字列の大小関係を比較することが出来ます。 このことについては[[programming/netfx/string/2_1_comparison]]で詳しく解説します。
-
#remarks-end
-

          
 
#navi(..)
#navi(..)
 

        

        

programming/netfx/string/1_operations/index.wiki.txt

current previous
10,7 10,7
 

        

        
 
なお、この文章ではUnicode正規形や正規化、サロゲートペアを含む文字列の扱いについては踏み込みません。 必要に応じて他のドキュメントを参照してください。
なお、この文章ではUnicode正規形や正規化、サロゲートペアを含む文字列の扱いについては踏み込みません。 必要に応じて他のドキュメントを参照してください。
 

        

        
~
*文字列の加工・編集
*Stringクラスと文字列の加工・編集
 
ここで解説する文字列の加工・編集の操作と、対応するStringクラスのメソッドを表にまとめます。 個々のメソッドの詳細については順に解説していきます。
ここで解説する文字列の加工・編集の操作と、対応するStringクラスのメソッドを表にまとめます。 個々のメソッドの詳細については順に解説していきます。
 

        

        
 
|*文字列操作と対応するStringクラスのメソッド
|*文字列操作と対応するStringクラスのメソッド
31,10 31,10
 
|Char配列から単一文字列への変換|Stringコンストラクタ|[[解説へ>#String..ctor]]|
|Char配列から単一文字列への変換|Stringコンストラクタ|[[解説へ>#String..ctor]]|
 
|~文字列操作|~対応するStringクラスのメソッド|~解説へのリンク|f
|~文字列操作|~対応するStringクラスのメソッド|~解説へのリンク|f
 

        

        
~
なお、文字列の探索と比較については[[programming/netfx/string/2_1_comparison]]で解説します。 また、Stringクラスのメソッドではワイルドカードのようなパターンマッチングを使った文字列の加工・編集は出来ないので、そういった場合は[[正規表現(Regexクラス)>programming/netfx/regex/0_abstract]]を使います。
なお、文字列の検索と比較については[[programming/netfx/string/2_1_comparison]]で解説します。 また、Stringクラスのメソッドではワイルドカードのようなパターンマッチングを使った文字列の加工・編集は出来ないので、そういった場合は[[正規表現(Regexクラス)>programming/netfx/regex/0_abstract]]を使います。
 

        

        
 
**連結 (Concat, +, +=) [#String.Concat]
**連結 (Concat, +, +=) [#String.Concat]
~
&msdn(netfx,member,System.String.Concat){String.Concatメソッド};は文字列同士の連結を行う静的メソッドで、任意の数の文字列を連結出来ます。 またC#、VBでは加算演算子``+``、および複合代入の加算演算子``+=``を使った連結もできるようになっています。
&msdn(netfx,member,System.String.Concat){String.Concatメソッド};は文字列同士の連結を行う静的メソッドで、任意の数の文字列を連結出来ます。 またC#、VBでは加算演算子+、および複合代入の加算演算子+=を使った連結もできるようになっています。
 

        

        
 
#tabpage(codelang=cs)
#tabpage(codelang=cs)
 
#code{{
#code{{
105,7 105,7
 
barqux
barqux
 
}}
}}
 

        

        
~
.NET Framework 4からは、``IEnumerable<String>``を引数にとるバージョンのConcatも用意されています。 これを利用すると[[List>programming/netfx/collections/2_generic_1_list]]に格納されている複数の文字列を一つに連結するということがメソッド呼び出し一つで行えます。
.NET Framework 4からは、IEnumerable<String>を引数にとるバージョンのConcatも用意されています。
 

        

        
 
#code(cs){{
#code(cs){{
 
using System;
using System;
127,7 127,7
 
}}
}}
 

        

        
 
**複製 (Copy) [#String.Copy]
**複製 (Copy) [#String.Copy]
~
&msdn(netfx,member,System.String.Copy){String.Copyメソッド};は文字列の複製を行う静的メソッドです。 見かけ上の動作は文字列変数の単なる代入と似ていますが、Copyメソッドでは''指定された文字列と同じ内容の新しいインスタンスが作成される''点が異なります。
&msdn(netfx,member,System.String.Copy){String.Copyメソッド};は文字列の複製を行う静的メソッドです。 見かけ上の動作は文字列変数の単なる代入と似ていますが、Copyメソッドでは指定された文字列と同じ内容の新しいインスタンスが作成される点が異なります。
 

        

        
 
#tabpage(codelang=cs)
#tabpage(codelang=cs)
 
#code{{
#code{{
177,9 177,7
 
foo False
foo False
 
}}
}}
 

        

        
+
#remarks
 
代入と複製の違い、参照の比較については[[programming/netfx/cloning]]や[[programming/netfx/valuetype_referencetype#equality]]などを参照してください。
代入と複製の違い、参照の比較については[[programming/netfx/cloning]]や[[programming/netfx/valuetype_referencetype#equality]]などを参照してください。
+
#remarks-end
 

        

        
 
**切り出し (Substring) [#String.Substring]
**切り出し (Substring) [#String.Substring]
 
&msdn(netfx,member,System.String.Substring){String.Substringメソッド};は文字列から部分文字列を切り出すメソッドで、切り出す最初のインデックスと長さを指定することで文字列の一部分を取得します。 長さを指定しなかった場合は、指定されたインデックスから文字列の最後までが返されます。
&msdn(netfx,member,System.String.Substring){String.Substringメソッド};は文字列から部分文字列を切り出すメソッドで、切り出す最初のインデックスと長さを指定することで文字列の一部分を取得します。 長さを指定しなかった場合は、指定されたインデックスから文字列の最後までが返されます。
257,12 255,8
 
The quick brown fox jumps over the lazy white dog
The quick brown fox jumps over the lazy white dog
 
}}
}}
 

        

        
+
#remarks
+
このメソッドでは、元の文字列には変更を加えず、挿入した結果を新しい文字列として返します。
+
#remarks-end
+

          
 
**削除 (Remove) [#String.Remove]
**削除 (Remove) [#String.Remove]
~
&msdn(netfx,member,System.String.Remove){String.Removeメソッド};は文字列の一部分を削除した文字列を取得するメソッドで、削除を始める最初のインデックスと長さを指定することで文字列の一部分を削除します。 長さを指定しなかった場合は、指定されたインデックスから文字列の最後までが削除されます。
&msdn(netfx,member,System.String.Remove){String.Removeメソッド};は文字列の一部分を削除するメソッドで、削除を始める最初のインデックスと長さを指定することで文字列の一部分を削除します。 長さを指定しなかった場合は、指定されたインデックスから文字列の最後までが削除されます。
 

        

        
 
#tabpage(codelang=cs)
#tabpage(codelang=cs)
 
#code{{
#code{{
302,13 296,7
 
The quick brown fox jumps
The quick brown fox jumps
 
}}
}}
 

        

        
~
#remarks
位置を指定した削除ではなく、部分文字列を指定した削除にはReplaceメソッドを使用します。
+
このメソッドでは、元の文字列には変更を加えず、削除した結果を新しい文字列として返します。
+
#remarks-end
+

          
+
#remarks
+
位置を指定した削除ではなく、部分文字列を指定した削除(特定の文字列の削除)には[[Replaceメソッド>#String.Replace]]を使用します。
+
#remarks-end
 

        

        
 
**置換 (Replace) [#String.Replace]
**置換 (Replace) [#String.Replace]
 
&msdn(netfx,member,System.String.Replace){String.Replaceメソッド};は文字列内の部分文字列を別の部分文字列に置き換えるメソッドです。 一致する文字列はすべて置き換えられます。
&msdn(netfx,member,System.String.Replace){String.Replaceメソッド};は文字列内の部分文字列を別の部分文字列に置き換えるメソッドです。 一致する文字列はすべて置き換えられます。
351,10 339,6
 
The quick brown fox jumps over the silly dog
The quick brown fox jumps over the silly dog
 
}}
}}
 

        

        
+
#remarks
+
このメソッドでは、元の文字列には変更を加えず、置換した結果を新しい文字列として返します。
+
#remarks-end
+

          
 
置き換え後の文字列にnull/Nothingもしくは空文字(String.Empty)を指定すると、置き換え前の部分文字列を削除することが出来ます。
置き換え後の文字列にnull/Nothingもしくは空文字(String.Empty)を指定すると、置き換え前の部分文字列を削除することが出来ます。
 

        

        
 
#tabpage(codelang=cs)
#tabpage(codelang=cs)
610,7 594,7
 
The<>quick<>brown<>fox<>jumps<>over<>the<>lazy<>dog
The<>quick<>brown<>fox<>jumps<>over<>the<>lazy<>dog
 
}}
}}
 

        

        
~
.NET Framework 4からは、``IEnumerable<String>``を引数にとるバージョンのJoinも用意されています。 これを利用すると[[List>programming/netfx/collections/2_generic_1_list]]に格納されている複数の文字列を一つに結合するということがメソッド呼び出し一つで行えます。
.NET Framework 4からは、IEnumerable<String>を引数にとるバージョンのJoinも用意されています。
 

        

        
 
#code(cs){{
#code(cs){{
 
using System;
using System;
675,11 659,9
 
<   The quick brown fox jumps over the lazy dog>
<   The quick brown fox jumps over the lazy dog>
 
}}
}}
 

        

        
~
#remarks
空白文字として扱われる文字には、スペース、タブの他、改行文字も含まれます。 詳細は.NET Frameworkのドキュメントを参照してください。
+
このメソッドでは、半角および全角のスペースやタブだけでなく、改行文字なども空白文字として扱われます。 .NET Framework 4以降では、Unicodeで空白文字と定義されている文字(&msdn(netfx,member,System.Char.IsWhiteSpace){Char.IsWhiteSpace};が``true``となる文字)が空白文字として扱われます。 それ以前のバージョンでの空白文字の扱いなど詳細は.NET Frameworkのドキュメントを参照してください。
+
#remarks-end
 

        

        
~
また、削除する文字を明示的に指定することも出来ます。 この場合、スペース以外の文字も指定することが出来ます。
また、削除する文字を指定することも出来ます。 この場合、スペース以外の文字も指定することが出来ます。
 

        

        
 
#tabpage(codelang=cs)
#tabpage(codelang=cs)
 
#code{{
#code{{
725,7 707,7
 
}}
}}
 

        

        
 
**余白の挿入 (PadLeft, PadRight) [#String.PadLeftPadRight]
**余白の挿入 (PadLeft, PadRight) [#String.PadLeftPadRight]
~
&msdn(netfx,member,System.String.PadLeft){String.PadLeftメソッド};は余白の挿入を行うメソッドで、指定された文字数になるように左側にスペースを挿入します。s &msdn(netfx,member,System.String.PadRight){String.PadRightメソッド};はPadLeftメソッドとは逆に右側にスペースを挿入します。 指定された文字数より文字列の長さの方が大きい場合、スペースは挿入されません。 このメソッドを使うことで文字列を左寄せ・右寄せすることができます。
&msdn(netfx,member,System.String.PadLeft){String.PadLeftメソッド};は余白の挿入を行うメソッドで、指定された文字数になるように左側にスペースを挿入します。 &msdn(netfx,member,System.String.PadRight){String.PadRightメソッド};はPadLeftメソッドとは逆に右側にスペースを挿入します。 指定された文字数より文字列の長さの方が大きい場合、スペースは挿入されません。
 

        

        
 
#tabpage(codelang=cs)
#tabpage(codelang=cs)
 
#code{{
#code{{
805,11 787,6
 
<foo--->
<foo--->
 
}}
}}
 

        

        
+
#remarks
+
中寄せ(センタリング)を行うように余白を挿入するメソッドは用意されていないので、そういった場合には独自に実装する必要があります。 実装例は[[#string_centering]]を参照してください。
+
#remarks-end
+

          
+

          
 
**大文字化・小文字化 (ToUpper, ToLower, ToUpperInvariant, ToLowerInvariant) [#String.ToUpperToLower]
**大文字化・小文字化 (ToUpper, ToLower, ToUpperInvariant, ToLowerInvariant) [#String.ToUpperToLower]
 
&msdn(netfx,member,System.String.ToUpper){String.ToUpperメソッド};は文字列を大文字化するメソッド、&msdn(netfx,member,System.String.ToLower){String.ToLowerメソッド};は文字列を小文字化するメソッドです。
&msdn(netfx,member,System.String.ToUpper){String.ToUpperメソッド};は文字列を大文字化するメソッド、&msdn(netfx,member,System.String.ToLower){String.ToLowerメソッド};は文字列を小文字化するメソッドです。
 

        

        
859,9 836,7
 
the quick brown fox jumps over the lazy dog
the quick brown fox jumps over the lazy dog
 
}}
}}
 

        

        
~
``ToUpper``/``ToUpperInvariant``と``ToLower``/``ToLowerInvariant``の違いは、大文字化・小文字化の際に参照される規則です。
ToUpper/ToUpperInvariantとToLower/ToLowerInvariantの違いは、大文字化・小文字化の際に参照される規則です。 例えば、トルコ語においては''i''の大文字は''I''(U+0049)ではなく''İ''(U+0131)で、''I''の小文字は''i''(U+0069)ではなく''ı''(U+0130)となるため、スレッドのカルチャがトルコ語の場合ToUpper/ToLowerの結果はToUpperInvariant/ToLowerInvariantと異なります。
+

          
+
例えば、トルコ語においては ''i'' の大文字は ''I''(U+0049) ではなく ''İ''(U+0131) で、''I'' の小文字は ''i''(U+0069) ではなく ''ı''(U+0130) となるため、スレッドのカルチャがトルコ語の場合``ToUpper``/``ToLower``の結果は``ToUpperInvariant``/``ToLowerInvariant``と異なる結果となります。
 

        

        
 
#tabpage(codelang=cs)
#tabpage(codelang=cs)
 
#code{{
#code{{
918,7 893,7
 
I: i ı
I: i ı
 
}}
}}
 

        

        
~
したがって、カルチャや変換規則を強く意識する必要がある場合は``ToUpper``/``ToLower``を用いる必要があります。 一方それ以外の多くの場合は``ToUpperInvariant``/``ToLowerInvariant``で十分と言えます。
したがって、カルチャや変換規則を強く意識する必要がある場合はToUpper/ToLowerを用いる必要があり、それ以外の多くの場合はToUpperInvariant/ToLowerInvariantで十分と言えます。
 

        

        
 
#remarks
#remarks
 
カルチャと変換規則については[[StringComparisonとStringComparer>programming/netfx/string/2_2_compareoptions#StringComparisonStringComparer]]でも詳しく説明しています。
カルチャと変換規則については[[StringComparisonとStringComparer>programming/netfx/string/2_2_compareoptions#StringComparisonStringComparer]]でも詳しく説明しています。
1179,9 1154,9
 
ここではStringクラスで提供されない文字列操作と、それを実装する例を見ていきます。 以下の例では引数のチェック等は省略しています。
ここではStringクラスで提供されない文字列操作と、それを実装する例を見ていきます。 以下の例では引数のチェック等は省略しています。
 

        

        
 
**部分文字列の計上 (Count)
**部分文字列の計上 (Count)
~
Stringクラスでは文字列中に含まれる部分文字列の数を計上するメソッドは用意されていません。 以下は部分文字列の計上を行う例です。 Count1ではIndexOfメソッドを用いて部分文字列の探索を繰り返すことで数を計上しています。 Count2ではReplaceメソッドを用いて部分文字列を削除し、減った文字数をもとに計上しています。
Stringクラスでは文字列中に含まれる部分文字列の数を計上するメソッドは用意されていません。 以下は部分文字列の計上を行う例です。 Count1ではIndexOfメソッドを用いて部分文字列の検索を繰り返すことで数を計上しています。 Count2ではReplaceメソッドを用いて部分文字列を削除し、減った文字数をもとに計上しています。
 

        

        
~
#tabpage(codelang=cs,container-title=部分文字列の計上)
#tabpage(codelang=cs)
 
#code{{
#code{{
 
using System;
using System;
 

        

        
1273,10 1248,10
 
4
4
 
}}
}}
 

        

        
~
**反転 (Reverse) [#string_reverse]
**反転 (Reverse)
 
Stringクラスでは文字列の並びを反転するメソッドは用意されていません。 以下は文字列の反転を行う例です。 ToCharArrayメソッドを用いて一度Char配列にしてから、Array.Reverseメソッドにより反転したのちに再びStringに変換することで文字列の反転を実現しています。
Stringクラスでは文字列の並びを反転するメソッドは用意されていません。 以下は文字列の反転を行う例です。 ToCharArrayメソッドを用いて一度Char配列にしてから、Array.Reverseメソッドにより反転したのちに再びStringに変換することで文字列の反転を実現しています。
 

        

        
~
#tabpage(codelang=cs,container-title=文字列の反転)
#tabpage(codelang=cs)
 
#code{{
#code{{
 
using System;
using System;
 

        

        
1338,46 1313,6
 
るやでついつい はりとのかなのごか めごかめごか
るやでついつい はりとのかなのごか めごかめごか
 
}}
}}
 

        

        
+
LINQを用いて次のように実装することもできます。
+

          
+
#tabpage(codelang=cs,container-title=LINQを用いた文字列の反転)
+
#code{{
+
using System;
+
using System.Linq;
+

          
+
class Sample
+
{
+
  static void Main()
+
  {
+
    string s = "かごめかごめ かごのなかのとりは いついつでやる";
+
    string r = new String(s.Reverse().ToArray());
+

          
+
    Console.WriteLine(s);
+
    Console.WriteLine(r);
+
  }
+
}
+
}}
+
#tabpage(codelang=vb)
+
#code{{
+
Imports System
+
Imports System.Linq
+

          
+
Class Sample
+
  Shared Sub Main()
+
    Dim s As String = "かごめかごめ かごのなかのとりは いついつでやる"
+
    Dim r As New String(s.Reverse().ToArray())
+

          
+
    Console.WriteLine(s)
+
    Console.WriteLine(r)
+
  End Sub
+
End Class
+
}}
+
#tabpage-end
+

          
+
#prompt{{
+
かごめかごめ かごのなかのとりは いついつでやる
+
るやでついつい はりとのかなのごか めごかめごか
+
}}
 

        

        
 
**範囲を指定した置換
**範囲を指定した置換
 
[[Replaceメソッド>#String.Replace]]では、文字列の範囲を指定して別の文字列に置き換えることはできません。 そういった置換を行う場合は、[[Substringメソッド>#String.Substring]]で文字列を切り出したあと置き換えたい文字列と[[連結する>#String.Concat]]ようにします。 次の例では、位置を指定して文字列の一部分を置き換えるReplaceメソッドを作成しています。
[[Replaceメソッド>#String.Replace]]では、文字列の範囲を指定して別の文字列に置き換えることはできません。 そういった置換を行う場合は、[[Substringメソッド>#String.Substring]]で文字列を切り出したあと置き換えたい文字列と[[連結する>#String.Concat]]ようにします。 次の例では、位置を指定して文字列の一部分を置き換えるReplaceメソッドを作成しています。
1429,7 1364,7
 
}}
}}
 

        

        
 

        

        
~
**センタリング [#string_centering]
**センタリング
 
StringクラスではPadLeftによる左詰め、PadRightによる右詰めは行えますが、文字列の中寄せ(センタリング)を行うメソッドは用意されていません。 以下は文字列のセンタリングを行う例です。 指定された幅で文字列が中央に来るよう左右に空白を入れています。 文字数よりも幅が下回る場合はそのままにします。
StringクラスではPadLeftによる左詰め、PadRightによる右詰めは行えますが、文字列の中寄せ(センタリング)を行うメソッドは用意されていません。 以下は文字列のセンタリングを行う例です。 指定された幅で文字列が中央に来るよう左右に空白を入れています。 文字数よりも幅が下回る場合はそのままにします。
 

        

        
 
#tabpage(codelang=cs)
#tabpage(codelang=cs)
1505,7 1440,7
 
}}
}}
 

        

        
 
**乗算演算子 (*, *=)
**乗算演算子 (*, *=)
~
Stringクラスでは乗算演算子はサポートされていません。 いくつかの言語では、乗算演算子を使って同じ文字の並びを任意の回数だけ繰り替えした文字列を作ることが出来ますが、Stringクラスではそういった操作は用意されていません。 そのため、必要な回数だけ連結を繰り返す必要があります。
Stringクラスでは乗算演算子はサポートされていません。 いくつかの言語では乗算演算子を使って同じ文字の並びを任意の回数だけ繰り替えした文字列を作ることが出来ますが、Stringクラスではそういった操作は用意されていません。 そのため、必要な回数だけ連結を繰り返す必要があります。
 

        

        
 
#tabpage(codelang=cs)
#tabpage(codelang=cs)
 
#code{{
#code{{
1546,11 1481,7
 
}}
}}
 
#tabpage-end
#tabpage-end
 

        

        
~
#remarks
なお、Stringクラスのコンストラクタを使うことで、同じ文字を任意の回数だけ繰り替えした文字を作ることは出来ます。
+
この方法で長大な文字列を生成する場合は、パフォーマンスの観点から[[StringBuilderクラス>programming/netfx/string/4_stringbuilder]]を使うことも検討してください。
+
#remarks-end
+

          
+
なお、Stringクラスのコンストラクタを使うことで、''同じ文字''を任意の回数だけ繰り替えした文字を作ることは出来ます。
 

        

        
 
#tabpage(codelang=cs)
#tabpage(codelang=cs)
 
#code{{
#code{{
1560,7 1491,7
 
{
{
 
  static void Main()
  static void Main()
 
  {
  {
~
    string s = new string('あ', 10); // 'あ'を10回くりかえした文字列を作る
    string s = new string('あ', 10);
 

        

        
 
    Console.WriteLine(s);
    Console.WriteLine(s);
 
  }
  }
1572,7 1503,7
 

        

        
 
Class Sample
Class Sample
 
  Shared Sub Main()
  Shared Sub Main()
~
    Dim s As New String("あ"c, 10) ' "あ"を10回くりかえした文字列を作る
    Dim s As New String("あ"c, 10)
 

        

        
 
    Console.WriteLine(s)
    Console.WriteLine(s)
 
  End Sub
  End Sub
1587,7 1518,7
 
*VBの文字列操作関数
*VBの文字列操作関数
 
(このドキュメントは未整理です)
(このドキュメントは未整理です)
 

        

        
~
現在はあまり推奨されませんが、Microsoft.VisualBasic名前空間の&msdn(netfx,type,Microsoft.VisualBasic.dll,Microsoft.VisualBasic.Strings){Stringsクラス};のメソッドを使うことで、VB由来の文字列操作関数を使うことも出来ます。 VB.NETでもこれらの関数を使うことは出来ますが、新規に書くコードではできるだけStringクラスのメソッドを使うべきです。 これらの文字列操作関数ではインデックスが1から始まる(1-based)として扱われる一方、.NET Frameworkでは0から始まる(0-based)として扱われるため、混乱を招いたり意図しない動作となる可能性があります。
あまり推奨は出来ませんが、Microsoft.VisualBasic名前空間の&msdn(netfx,type,Microsoft.VisualBasic.dll,Microsoft.VisualBasic.Strings){Stringsクラス};のメソッドを使うことで、VB由来の文字列操作関数を使うことも出来ます。 VB.NETでもこれらの関数を使うことは出来ますが、新規に書くコードではできるだけStringクラスのメソッドを使うべきです。 これらの文字列操作関数ではインデックスが1から始まる(1-based)として扱われる一方、.NET Frameworkでは0から始まる(0-based)として扱われるため、混乱を招いたり意図しない動作となる可能性があります。
 

        

        
 
#code(cs){{
#code(cs){{
 
using System;
using System;

programming/netfx/string/2_1_comparison/index.wiki.txt

current previous
1,18 1,18
~
${smdncms:title,文字列の探索・比較}
${smdncms:title,文字列の検索・比較}
 
${smdncms:keywords,Equals,Comapre,CompareTo,Contains,StartsWith,EndsWith,IndexOf,IndexOfAny}
${smdncms:keywords,Equals,Comapre,CompareTo,Contains,StartsWith,EndsWith,IndexOf,IndexOfAny}
 
${smdncms:document_versions,codelang=cs,codelang=vb}
${smdncms:document_versions,codelang=cs,codelang=vb}
 

        

        
 
#navi(..)
#navi(..)
 

        

        
~
ここではStringクラスに用意されている文字列探索・比較の操作を行うためのメソッドについて見ていきます。 なお、探索・比較時のオプションとカルチャの規則に基づいた比較については、[[programming/netfx/string/2_2_compareoptions]]で解説します。
ここではStringクラスに用意されている文字列検索・比較の操作を行うためのメソッドについて見ていきます。 なお、検索・比較時のオプションとカルチャの規則に基づいた比較については、[[programming/netfx/string/2_2_compareoptions]]で解説します。
 
#adunit
#adunit
 

        

        
~
ここで解説する文字列の探索・比較の操作と、対応するStringクラスのメソッドを表にまとめます。 個々のメソッドの詳細については順に解説していきます。
ここで解説する文字列の検索・比較の操作と、対応するStringクラスのメソッドを表にまとめます。 個々のメソッドの詳細については順に解説していきます。
 

        

        
 
|*文字列操作と対応するStringクラスのメソッド
|*文字列操作と対応するStringクラスのメソッド
 
|~文字列操作|~対応するStringクラスのメソッド|~解説へのリンク|h
|~文字列操作|~対応するStringクラスのメソッド|~解説へのリンク|h
~
|部分文字列の探索&br;(部分文字列の位置の取得)|IndexOf (前方からの探索)&br;LastIndexOf (後方からの探索)|[[解説へ>#String.IndexOf]]|
|部分文字列の検索&br;(部分文字列の位置の取得)|IndexOf (前方からの検索)&br;LastIndexOf (後方からの検索)|[[解説へ>#String.IndexOf]]|
~
|任意の一文字の探索&br;(文字の位置の取得)|IndexOfAny (前方からの探索)&br;LastIndexOfAny (後方からの探索)|[[解説へ>#String.IndexOfAny]]|
|任意の一文字の検索&br;(文字の位置の取得)|IndexOfAny (前方からの検索)&br;LastIndexOfAny (後方からの検索)|[[解説へ>#String.IndexOfAny]]|
 
|部分文字列を含むかどうかの判定&br;(部分一致の判定)|Contains|[[解説へ>#String.Contains]]|
|部分文字列を含むかどうかの判定&br;(部分一致の判定)|Contains|[[解説へ>#String.Contains]]|
 
|部分文字列で始まるかどうかの判定&br;(前方一致の判定)|StartsWith|[[解説へ>#String.Contains]]|
|部分文字列で始まるかどうかの判定&br;(前方一致の判定)|StartsWith|[[解説へ>#String.Contains]]|
 
|部分文字列で終わるかどうかの判定&br;(後方一致の判定)|EndsWith|[[解説へ>#String.Contains]]|
|部分文字列で終わるかどうかの判定&br;(後方一致の判定)|EndsWith|[[解説へ>#String.Contains]]|
23,15 23,15
 
|序数による文字列の大小関係の比較|CompareOrdinal|[[解説へ>#String.CompareOrdinal]]|
|序数による文字列の大小関係の比較|CompareOrdinal|[[解説へ>#String.CompareOrdinal]]|
 
|~文字列操作|~対応するStringクラスのメソッド|~解説へのリンク|f
|~文字列操作|~対応するStringクラスのメソッド|~解説へのリンク|f
 

        

        
~
Stringクラスのメソッドではワイルドカードのようなパターンマッチングを使った文字列の探索・比較は出来ないので、そういった場合は[[正規表現(Regexクラス)>programming/netfx/regex/0_abstract]]を使います。
Stringクラスのメソッドではワイルドカードのようなパターンマッチングを使った文字列の検索・比較は出来ないので、そういった場合は[[正規表現(Regexクラス)>programming/netfx/regex/0_abstract]]を使います。
 

        

        
 
なお、文字列の加工と編集については[[programming/netfx/string/1_operations]]で解説しています。 また、この文章ではUnicode正規形や正規化、サロゲートペアを含む文字列には踏み込みません。 必要に応じて他のドキュメントを参照してください。
なお、文字列の加工と編集については[[programming/netfx/string/1_operations]]で解説しています。 また、この文章ではUnicode正規形や正規化、サロゲートペアを含む文字列には踏み込みません。 必要に応じて他のドキュメントを参照してください。
 

        

        
~
*文字列の探索 [#string_searching]
*Stringクラスと文字列の検索
~
ここでは文字列の探索などを行うためのメソッドについて見ていきます。
ここでは文字列の検索などを行うためのメソッドについて見ていきます。
 

        

        
~
**部分文字列の探索 (IndexOf, LastIndexOf) [#String.IndexOf]
**部分文字列の検索 (IndexOf, LastIndexOf) [#String.IndexOf]
~
&msdn(netfx,member,System.String.IndexOf){String.IndexOfメソッド};は文字列内にある部分文字列の位置を探索するメソッドで、文字列内にある部分文字列の最初のインデックスを返します。 文字列内に部分文字列がない場合は-1が返されます。
&msdn(netfx,member,System.String.IndexOf){String.IndexOfメソッド};は文字列内にある部分文字列の位置を検索するメソッドで、文字列内にある部分文字列の最初のインデックスを返します。 文字列内に部分文字列がない場合は-1が返されます。
 

        

        
 
#tabpage(codelang=cs)
#tabpage(codelang=cs)
 
#code{{
#code{{
71,7 71,7
 
-1
-1
 
}}
}}
 

        

        
~
&msdn(netfx,member,System.String.LastIndexOf){String.LastIndexOfメソッド};はIndexOfメソッドとは異なり、後ろから探索を行い、文字列内にある部分文字列の最後のインデックスを返します。 文字列内に部分文字列がない場合はIndexOfメソッドと同様に-1が返されます。
&msdn(netfx,member,System.String.LastIndexOf){String.LastIndexOfメソッド};はIndexOfメソッドとは異なり、後ろから検索を行い、文字列内にある部分文字列の最後のインデックスを返します。 文字列内に部分文字列がない場合はIndexOfメソッドと同様に-1が返されます。
 

        

        
 
#tabpage(codelang=cs)
#tabpage(codelang=cs)
 
#code{{
#code{{
114,7 114,7
 
-1
-1
 
}}
}}
 

        

        
~
IndexOfメソッド、LastIndexOfメソッドでは文字列ではなく文字(char)の位置を探索することも出来ます。 文字列内に指定された文字がない場合は同様に-1が返されます。
IndexOfメソッド、LastIndexOfメソッドでは文字列ではなく文字(char)の位置を検索することも出来ます。 文字列内に指定された文字がない場合は同様に-1が返されます。
 

        

        
 
#tabpage(codelang=cs)
#tabpage(codelang=cs)
 
#code{{
#code{{
157,7 157,7
 
-1
-1
 
}}
}}
 

        

        
~
IndexOfメソッド、LastIndexOfメソッドでは、文字列比較時のオプションを指定することができ、例えば大文字小文字の違いを無視した探索を行うことも出来ます。 文字列比較時のオプションについては[[StringComparisonとStringComparer>programming/netfx/string/2_2_compareoptions#StringComparisonStringComparer]]で詳しく説明します。
IndexOfメソッド、LastIndexOfメソッドでは、文字列比較時のオプションを指定することができ、例えば大文字小文字の違いを無視した検索を行うことも出来ます。 文字列比較時のオプションについては[[StringComparisonとStringComparer>programming/netfx/string/2_2_compareoptions#StringComparisonStringComparer]]で詳しく説明します。
 

        

        
 
#tabpage(codelang=cs)
#tabpage(codelang=cs)
 
#code{{
#code{{
200,8 200,8
 
8
8
 
}}
}}
 

        

        
~
**任意の文字の探索 (IndexOfAny, LastIndexOfAny) [#String.IndexOfAny]
**任意の文字の検索 (IndexOfAny, LastIndexOfAny) [#String.IndexOfAny]
~
&msdn(netfx,member,System.String.IndexOfAny){String.IndexOfAnyメソッド};は指定された複数の文字の中で、文字列内で見つかった最初の位置を探索するメソッドです。 IndexOfメソッド同様、いずれの文字も見つからなかった場合は-1が返されます。
&msdn(netfx,member,System.String.IndexOfAny){String.IndexOfAnyメソッド};は指定された複数の文字の中で、文字列内で見つかった最初の位置を検索するメソッドです。 IndexOfメソッド同様、いずれの文字も見つからなかった場合は-1が返されます。
 

        

        
 
#tabpage(codelang=cs)
#tabpage(codelang=cs)
 
#code{{
#code{{
244,7 244,7
 
0
0
 
}}
}}
 

        

        
~
&msdn(netfx,member,System.String.LastIndexOfAny){String.LastIndexOfAnyメソッド};は、後ろから探索を行い、文字列内で見つかった最後の位置を返します。
&msdn(netfx,member,System.String.LastIndexOfAny){String.LastIndexOfAnyメソッド};は、後ろから検索を行い、文字列内で見つかった最後の位置を返します。
 

        

        
 
#tabpage(codelang=cs)
#tabpage(codelang=cs)
 
#code{{
#code{{
504,7 504,7
 
True
True
 
}}
}}
 

        

        
~
*文字列の比較・等価性の検証 [#string_comparison]
*Stringクラスと比較・等価性の検証
 
ここでは文字列の比較・等価性の検証などを行うためのメソッドについて見ていきます。
ここでは文字列の比較・等価性の検証などを行うためのメソッドについて見ていきます。
 

        

        
 
**null、空文字、空白のチェック (IsNullOrEmpty, IsNullOrWhiteSpace) [#String.IsNullOrEmpty]
**null、空文字、空白のチェック (IsNullOrEmpty, IsNullOrWhiteSpace) [#String.IsNullOrEmpty]
581,9 581,7
 
<> : IsNullOrWhiteSpace = True
<> : IsNullOrWhiteSpace = True
 
}}
}}
 

        

        
~
#remarks
空白文字として扱われる文字には、スペース、タブの他、改行文字も含まれます。 詳細は.NET Frameworkのドキュメントを参照してください。
+
このメソッドでは、半角および全角のスペースやタブだけでなく、改行文字なども空白文字として扱われます。 具体的には、Unicodeで空白文字と定義されている文字(&msdn(netfx,member,System.Char.IsWhiteSpace){Char.IsWhiteSpace};が``true``となる文字)が空白文字として扱われます。
+
#remarks-end
 

        

        
 
なお、IsNullOrEmptyメソッド、IsNullOrWhiteSpaceメソッドの動作は、次のコードと等価です。
なお、IsNullOrEmptyメソッド、IsNullOrWhiteSpaceメソッドの動作は、次のコードと等価です。
 

        

        
868,9 866,7
 
}}
}}
 

        

        
 
**序数による比較 (CompareOrdinal) [#String.CompareOrdinal]
**序数による比較 (CompareOrdinal) [#String.CompareOrdinal]
~
&msdn(netfx,member,System.String.CompareOrdinal){String.CompareOrdinalメソッド};は、[[Compareメソッド>#String.CompareTo]]同様に文字列の比較を行う静的メソッドですが、比較の際に文字列の各文字を数値(''Unicode序数''、''Unicode ordinal'')、つまり各文字の''コードポイント''での比較を行う点で動作が異なります。
&msdn(netfx,member,System.String.CompareOrdinal){String.CompareOrdinalメソッド};はCompareメソッド同様、文字列の比較を行う静的メソッドですが、Compareメソッドが現在のスレッドの(もしくは引数で指定された)カルチャの規則にしたがった比較を行うのに対し、CompareOrdinalメソッドではカルチャに依存せず、比較の際には文字列の各文字を数値(Unicode序数、Unicode ordinal)、つまりコードポイントで比較します。
+

          
+
Compareメソッドが現在のスレッドの(もしくは引数で指定された)カルチャの規則にしたがった比較を行うのに対し、CompareOrdinalメソッドではカルチャに依存しない比較が行われます。
 

        

        
 
#tabpage(codelang=cs)
#tabpage(codelang=cs)
 
#code{{
#code{{
977,9 973,9
 
foo != foo: False
foo != foo: False
 
}}
}}
 

        

        
~
当然ながら、等価演算子・不等価演算子による比較の場合は、カルチャを無視したり大文字小文字を無視したりといった文字列比較時のオプション([[StringComparison>programming/netfx/string/2_2_compareoptions#StringComparison]])を指定することはできません。 文字列比較時のオプションを指定する必要がある場合はEqualsメソッドを用います。
当然ながら、等価演算子・不等価演算子による比較の場合は、カルチャを無視したり大文字小文字を無視したりといった文字列比較時のオプション([[StringComparison>programming/netfx/string/2_2_compareoptions#StringComparison]])を指定することはできません。 そういった場合は、Equalsメソッドを用いる必要があります。
 

        

        
~
また、C#において、等価演算子・不等価演算子がオーバーロードされていない限り、両辺がstringでないとコンパイルエラーとなります(タイプセーフ)。 一方、Equalsメソッドは引数にObject型をとるオーバーロードも用意されているため、stringと異なる型の比較を行おうとしてもコンパイルエラーにはなりません。
また、C#において、等価演算子・不等価演算子がオーバーロードされていない限り、両辺がstringでないとコンパイルエラーとなります(タイプセーフ)。 Equalsメソッドは、引数にObject型をとるオーバーロードも用意されているため、string同士以外でもコンパイルエラーとはなりません。 等価演算子とEqualsメソッドではパフォーマンスに若干の違いはありますが、どちらを使うのが妥当かは状況により異なるので、両者の違いを十分に考慮して選択する必要があります。
 

        

        
 
#code(cs){{
#code(cs){{
 
using System;
using System;
991,18 987,12
 
    string s = "16";
    string s = "16";
 
    int i = 16;
    int i = 16;
 

        

        
~
    // 等価演算子では、stringとintの比較はコンパイルエラーとなる
    // Console.WriteLine(s == i); // stringとintでは等価演算子による比較は出来ない
~
    Console.WriteLine(s == i); // error CS0019: 演算子 '==' を 'string' と 'int' 型のオペランドに適用することはできません。
    Console.WriteLine(String.Equals(s, i)); // Equalsメソッドでは、stringとintでも比較は出来る
+

          
+
    // Equalsメソッドでは、stringとintの比較はコンパイルエラーにはならない
+
    // また実行時にも例外はスローされない
+
    Console.WriteLine(String.Equals(s, i));
 
  }
  }
 
}
}
 
}}
}}
 

        

        
+
等価演算子とEqualsメソッドではパフォーマンスに若干の違いはありますが、どちらを使うのが妥当かは状況により異なるので、両者の違いを十分に考慮して選択する必要があります。
+

          
 
**比較演算子 (<, <=, >, >=, Like)
**比較演算子 (<, <=, >, >=, Like)
 
(このドキュメントは未整理です)
(このドキュメントは未整理です)
 

        

        

programming/netfx/string/2_2_compareoptions/index.wiki.txt

current previous
8,8 8,6
 

        

        
 
なお、このページで解説する比較操作に関連するインターフェイスについてや、コレクションとソートについて、カルチャと文字列操作については以下のページで詳しく解説しているので必要に応じて参照してください。
なお、このページで解説する比較操作に関連するインターフェイスについてや、コレクションとソートについて、カルチャと文字列操作については以下のページで詳しく解説しているので必要に応じて参照してください。
 

        

        
+
#relevantdocs
+

          
 
#ls2_1(programming/netfx/comparison,pathsort)
#ls2_1(programming/netfx/comparison,pathsort)
 
#ls2_1(programming/netfx/locale,pathsort)
#ls2_1(programming/netfx/locale,pathsort)
 
-[[programming/netfx/sorting]]
-[[programming/netfx/sorting]]
17,126 15,17
 
--[[programming/netfx/collections/2_generic_1_list]]
--[[programming/netfx/collections/2_generic_1_list]]
 
--[[programming/netfx/collections/2_generic_2_dictionary]]
--[[programming/netfx/collections/2_generic_2_dictionary]]
 

        

        
+
#relevantdocs-end
+

          
+
#remarks
 
この文章では一部で特殊記号を使っています。 ブラウザで使用しているフォントによっては正しく表示されない文字があるかもしれません。
この文章では一部で特殊記号を使っています。 ブラウザで使用しているフォントによっては正しく表示されない文字があるかもしれません。
+
#remarks-end
+

          
+
#remarks
+
この文章では実行環境のロケール設定によって動作や結果が変わる場合のあるトピックを扱っています。 特に言及のない限りはja-JP(日本語/日本)の環境で実行した場合について解説しています。
+
#remarks-end
 

        

        
 
#adunit
#adunit
 

        

        
 
*StringComparison列挙型とStringComparerクラス [#StringComparisonStringComparer]
*StringComparison列挙型とStringComparerクラス [#StringComparisonStringComparer]
~
[[String.CompareメソッドやString.Equalsメソッド>programming/netfx/string/2_1_comparison#String.CompareTo]]などをはじめとして、.NET Frameworkでは文字列比較の際に比較オプションを指定することでその動作を変更することができます。
.NET Frameworkでは、文字列比較の際の動作を指定することができます。 単純な比較のほか、大文字小文字の無視、特定カルチャに依存した並べ替え規則の適用などを状況に応じて選択できます。
+

          
+
一例として、大文字と小文字の違いを無視して2つの文字列が等しいかどうか比較したい場合は次のようにします。
+

          
+
#tabpage(codelang=cs,container-title=大文字と小文字の違いを無視した文字列比較の例)
+
#code{{
+
using System;
+

          
+
class Sample
+
{
+
  static void Main()
+
  {
+
    string s1 = "foo";
+
    string s2 = "FOO";
+

          
+
    // 通常の文字列比較
+
    // (s1とs2は等しくないと判断される)
+
    Console.WriteLine(String.Equals(s1, s2));
+

          
+
    // 大文字小文字の違いを無視して文字列を比較する
+
    // (s1とs2は等しいと判断される)
+
    Console.WriteLine(String.Equals(s1, s2, StringComparison.InvariantCultureIgnoreCase));
+
  }
+
}
+
}}
+
#tabpage(codelang=vb)
+
#code{{
+
Imports System
+

          
+
Class Sample
+
  Shared Sub Main()
+
    Dim s1 As String = "foo"
+
    Dim s2 As String = "FOO"
+

          
+
    ' 通常の文字列比較
+
    ' (s1とs2は等しくないと判断される)
+
    Console.WriteLine(String.Equals(s1, s2))
+

          
+
    ' 大文字小文字の違いを無視して文字列を比較する
+
    ' (s1とs2は等しいと判断される)
+
    Console.WriteLine(String.Equals(s1, s2, StringComparison.InvariantCultureIgnoreCase))
+
  End Sub
+
End Class
+
}}
+
#tabpage-end
+

          
+
#prompt{{
+
False
+
True
+
}}
+

          
+
上記の例では[[StringComparison列挙型>#StringComparison]]で文字列の比較オプションを指定しています。
+

          
+
また別の例として、大文字と小文字の違いを無視してキーを扱うDictionaryを作成したい場合は次のようにします。
+

          
+
#tabpage(codelang=cs,container-title=Dictionaryでのキー比較規則を指定する例)
+
#code{{
+
using System;
+
using System.Collections.Generic;
+

          
+
class Sample
+
{
+
  static void Main()
+
  {
+
    // キーの大文字小文字の違いを無視するDictionaryを作成する
+
    Dictionary<string, string> dict = new Dictionary<string, string>(StringComparer.InvariantCultureIgnoreCase);
+

          
+
    // キー"foo"に値を設定
+
    dict["foo"] = "bar";
+

          
+
    // キー"FOO"の値を参照
+
    Console.WriteLine(dict["FOO"]); // KeyNotFoundExceptionはスローされない
+
  }
+
}
+
}}
+
#tabpage(codelang=vb)
+
#code{{
+
Imports System
+
Imports System.Collections.Generic
+

          
+
Class Sample
+
  Shared Sub Main()
+
    ' キーの大文字小文字の違いを無視するDictionaryを作成する
+
    Dim dict As New Dictionary(Of String, String)(StringComparer.InvariantCultureIgnoreCase)
+

          
+
    ' キー"foo"に値を設定
+
    dict("foo") = "bar"
+

          
+
    ' キー"FOO"の値を参照
+
    Console.WriteLine(dict("FOO")) ' KeyNotFoundExceptionはスローされない
+
  End Sub
+
End Class
+
}}
+
#tabpage-end
+

          
+
#prompt{{
+
bar
+
}}
+

          
+
上記の例では[[StringComparerクラス>#StringComparer]]を指定することでDictionaryのキー比較処理をカスタマイズしています。
+

          
+
このように、大文字小文字の無視の他にも特定カルチャに依存した(あるいは依存しない)並べ替え規則の適用など、目的に応じて比較オプションを選択することができます。
 

        

        
 
**StringComparison列挙型 [#StringComparison]
**StringComparison列挙型 [#StringComparison]
 
&msdn(netfx,type,System.StringComparison){StringComparison列挙型};は、文字列比較の際の動作を指定するための列挙型で、次のメソッドにおいて文字列比較を行う際にオプションとして指定出来ます。
&msdn(netfx,type,System.StringComparison){StringComparison列挙型};は、文字列比較の際の動作を指定するための列挙型で、次のメソッドにおいて文字列比較を行う際にオプションとして指定出来ます。
 

        

        
~
-StringComparisonを引数に指定することができるメソッド
-StringComparisonを引数にとるメソッド
 
--&msdn(netfx,member,System.String.Compare){String.Compareメソッド};
--&msdn(netfx,member,System.String.Compare){String.Compareメソッド};
 
--&msdn(netfx,member,System.String.Equals){String.Equalsメソッド};
--&msdn(netfx,member,System.String.Equals){String.Equalsメソッド};
 
--&msdn(netfx,member,System.String.IndexOf){String.IndexOfメソッド};
--&msdn(netfx,member,System.String.IndexOf){String.IndexOfメソッド};
145,27 34,14
 
--&msdn(netfx,member,System.String.EndsWith){String.EndsWithメソッド};
--&msdn(netfx,member,System.String.EndsWith){String.EndsWithメソッド};
 

        

        
 
また、StringComparisonを指定する場合は、次のいずれかを指定できます。
また、StringComparisonを指定する場合は、次のいずれかを指定できます。
~
|*StringComparisonの値と文字列比較時の動作
|*StringComparison
~
|~StringComparisonの値|>|~文字列比較時の動作|h
|~StringComparisonの値|~文字列比較時の動作|h
~
|~|~大文字小文字の違い|~比較の規則|h
|StringComparison.CurrentCulture|現在のカルチャの並べ替え規則に基づいて比較する&br;(StringComparisonを指定しない場合はこの動作になります)|
~
|&msdn(netfx,member,System.StringComparison.CurrentCulture){StringComparison.CurrentCulture};|無視しない|現在のカルチャの並べ替え規則に基づいて比較する|
|StringComparison.CurrentCultureIgnoreCase|現在のカルチャの並べ替え規則に基づいて比較する&br;大文字小文字の違いは無視する|
~
|&msdn(netfx,member,System.StringComparison.CurrentCultureIgnoreCase){StringComparison.CurrentCultureIgnoreCase};|無視する|~|
|StringComparison.InvariantCulture|インバリアントカルチャの並べ替え規則に基づいて比較する|
~
|&msdn(netfx,member,System.StringComparison.InvariantCulture){StringComparison.InvariantCulture};|無視しない|インバリアントカルチャの並べ替え規則に基づいて比較する|
|StringComparison.InvariantCultureIgnoreCase|インバリアントカルチャの並べ替え規則に基づいて比較する&br;大文字小文字の違いは無視する|
~
|&msdn(netfx,member,System.StringComparison.InvariantCultureIgnoreCase){StringComparison.InvariantCultureIgnoreCase};|無視する|~|
|StringComparison.Ordinal|文字列の各文字を数値(Unicode序数、Unicode ordinal)=コードポイントで比較する|
~
|&msdn(netfx,member,System.StringComparison.Ordinal){StringComparison.Ordinal};|無視しない|文字列の各文字を数値(Unicode序数、Unicode ordinal)=コードポイントで比較する|
|StringComparison.OrdinalIgnoreCase|文字列の各文字を数値(Unicode序数、Unicode ordinal)=コードポイントで比較する&br;大文字小文字の違いは無視する|
+
|&msdn(netfx,member,System.StringComparison.OrdinalIgnoreCase){StringComparison.OrdinalIgnoreCase};|無視する|~|
+

          
+
#remarks
+
StringComparisonを指定しない場合は、StringComparison.CurrentCultureを指定した場合と同じ動作になります。
+
#remarks-end
+

          
+
#remarks
+
インバリアントカルチャについての解説は[[programming/netfx/locale/0_abstract#invariant_culture]]を参照してください。
+
#remarks-end
+

          
+
#remarks
+
全角と半角の違い・ひらがなとカタカナの違いを扱いたい場合は[[CompareOptions列挙型>#CompareOptions]]を使用することができます。
+
#remarks-end
 

        

        
 
以下はStringComparisonを指定して比較を行う例です。
以下はStringComparisonを指定して比較を行う例です。
 

        

        
251,12 127,12
 
-1
-1
 
}}
}}
 

        

        
~
***CurrentCultureとInvariantCultureの違い [#StringComparison.CurrentCulture_vs_StringComparison.InvariantCulture]
***CurrentCulture(IgnoreCase)とInvariantCulture(IgnoreCase)の違い
~
CurrentCultureとInvariantCultureは、ともに特定のカルチャでの規則に基づいた比較を行う点では同じですが、CurrentCultureでは''現在のカルチャに基づいた比較''を行うのに対し、InvariantCultureでは特定の文化圏や言語に依存しない''インバリアントカルチャに基づいた比較''を行う点が異なります。
CurrentCulture(IgnoreCase)とInvariantCulture(IgnoreCase)は、特定のカルチャでの規則に基づいた比較を行う点では同じですが、CurrentCulture(IgnoreCase)では現在のカルチャに基づいた比較を行うのに対し、InvariantCulture(IgnoreCase)ではインバリアントカルチャ(特定の文化圏や言語に依存しない)に基づいた比較を行う点が異なります。
 

        

        
 
以下はString.Compareメソッドの結果を用いてこれらの違いを見るためのサンプルです。
以下はString.Compareメソッドの結果を用いてこれらの違いを見るためのサンプルです。
 

        

        
~
#tabpage(codelang=cs,container-title=CurrentCultureとInvariantCultureの違い)
#tabpage(codelang=cs)
 
#code{{
#code{{
 
using System;
using System;
 
using System.Globalization;
using System.Globalization;
317,19 193,11
 

        

        
 
スレッドのカルチャをen-US(英語/米国)に変更する前後の結果に注目してください。 InvariantCultureでの結果はどちらも変わらないのに対し、CurrentCultureでの結果は、スレッドのカルチャを変更する前後で異なっています。
スレッドのカルチャをen-US(英語/米国)に変更する前後の結果に注目してください。 InvariantCultureでの結果はどちらも変わらないのに対し、CurrentCultureでの結果は、スレッドのカルチャを変更する前後で異なっています。
 

        

        
~
これは、ja-JP(日本語/日本)の規則では漢字の読みによる並びとなっているために''亜''(あ)の方が''井''(い)より小さい(前に並ぶ)、つまり"''亜''<''井''"とされるのに対し、en-US(英語/米国)の規則では文字のコードポイントによる並びとなっているために、''井''(U+4E95)の方が''亜''(U+4E9C)よりも小さい(前に並ぶ)、つまり"''亜''>''井''"とされるためです。 そのため、CurrentCultureによる比較の結果は、カルチャがja-JPとen-USの場合で異なります。
これは、ja-JP(日本語/日本)の規則では漢字の読みによる並びとなっているために''亜''(あ)の方が''井''(い)より小さい(前に並ぶ)、つまり"''亜''<''井''"とされるのに対し、en-US(英語/米国)の規則では文字のコードポイントによる並びとなっているために''井''(U+4E95)の方が''亜''(U+4E9C)よりも小さい(前に並ぶ)、つまり"''亜''>''井''"とされるためです。 そのため、CurrentCultureによる比較の結果は、ja-JPとen-USにより異なります。 一方、InvariantCultureの場合は特定の言語に依存しない規則に基づいて比較されるため、ja-JPでもen-USでも''井''の方が''亜''よりも小さいというどちらも同じ結果となります。 (参考: &msdn(netfx,id,a7zyyk0c){固有カルチャのデータの比較と並べ替え};)
+

          
+
一方、InvariantCultureの場合は特定の言語に依存しない規則に基づいて比較されるため、カルチャがja-JPでもen-USでも''井''の方が''亜''よりも小さいというどちらも同じ結果となります。 (参考: &msdn(netfx,id,a7zyyk0c){固有カルチャのデータの比較と並べ替え};)
+

          
+
CurrentCultureIgnoreCaseとInvariantCultureIgnoreCaseの場合もこれと同様の動作となります。
+

          
+
#remarks
+
カルチャ情報についての詳細やカルチャ情報の取得・変更に関しては[[programming/netfx/locale/0_abstract]]で詳しく解説しています。
+
#remarks-end
 

        

        
 
続いて、CurrentCultureIgnoreCaseとInvariantCultureIgnoreCaseでも違いが現れる例を見てみます。
続いて、CurrentCultureIgnoreCaseとInvariantCultureIgnoreCaseでも違いが現れる例を見てみます。
 

        

        
~
#tabpage(codelang=cs,container-title=CurrentCultureIgnoreCaseとInvariantCultureIgnoreCaseで異なる結果となる例)
#tabpage(codelang=cs)
 
#code{{
#code{{
 
using System;
using System;
 
using System.Globalization;
using System.Globalization;
422,10 290,10
 

        

        
 
このように、特定の言語や文化圏に依存した規則に基づいて比較を行いたい場合はCurrentCulture(IgnoreCase)、特定の言語や文化圏に依存しない規則に基づいて比較を行いたい場合はInvariantCulture(IgnoreCase)を使用する必要があります。
このように、特定の言語や文化圏に依存した規則に基づいて比較を行いたい場合はCurrentCulture(IgnoreCase)、特定の言語や文化圏に依存しない規則に基づいて比較を行いたい場合はInvariantCulture(IgnoreCase)を使用する必要があります。
 

        

        
~
***CurrentCultureとOrdinalの違い [#StringComparison.CurrentCulture_vs_StringComparison.Ordinal]
***CurrentCulture(IgnoreCase)とOrdinal(IgnoreCase)の違い
~
CurrentCultureとInvariantCultureは特定のカルチャでの規則に基づいて比較を行いますが、一方Ordinalではカルチャに依存せず、文字列の各文字を数値(Unicode序数、Unicode ordinal)、つまり''コードポイントで比較''します。
CurrentCulture(IgnoreCase)とInvariantCulture(IgnoreCase)は、特定のカルチャでの規則に基づいて比較をいますが、Ordinal(IgnoreCase)ではカルチャの依存せず、文字列の各文字を数値(Unicode序数、Unicode ordinal)、つまりコードポイントで比較します。
 

        

        
~
#tabpage(codelang=cs,container-title=CurrentCultureとOrdinalの違い)
#tabpage(codelang=cs)
 
#code{{
#code{{
 
using System;
using System;
 

        

        
456,9 324,7
 
Compare Ordnal         : 7
Compare Ordnal         : 7
 
}}
}}
 

        

        
~
CurrentCultureとInvariantCultureの場合と結果が似ているので分かりにくいですが、CurrentCultureの場合は''亜''(あ)の方が''井''(い)より小さい(前に並ぶ)、つまり"''亜''<''井''"とされます。
CurrentCultureとInvariantCultureの場合と結果が似ているので分かりにくいですが、CurrentCultureの場合は''亜''(あ)の方が''井''(い)より小さい(前に並ぶ)、つまり"''亜''<''井''"とされるのに対し、Ordnalの場合は''井''(U+4E95)の方が''亜''(U+4E9C)よりも小さい(前に並ぶ)、つまり"''亜''>''井''"とされるため、上記のような結果となります。 (0x4E9C - 0x4E95 = 0x0007 = 7である点に注目するとわかりやすいかもしれません)
+

          
+
対してOrdnalの場合は、''井''(U+4E95)の方が''亜''(U+4E9C)よりも小さい(前に並ぶ)、つまり"''亜''>''井''"とされるため、上記のような結果となります。 (0x4E9C - 0x4E95 = 0x0007 = 7である点に注目するとわかりやすいかもしれません)
 

        

        
 
また、次のような例をとって違いを見てみます。
また、次のような例をとって違いを見てみます。
 

        

        
511,25 377,6
 

        

        
 
対してOrdinalの場合ですが、"coop"と"co-op"の3文字目を比較すると''o''(U+006F)と''-''(U+002D)であるため"''coop''>''co-op''"という結果になります。 同様に、"cant"と"can't"の3文字目は''t''(U+0074)と'(U+0027)であるため"''cant''>''can't''"という結果になります。 (この結果も、0x006F - 0x002D = 0x0042 = 66、0x0074-0x0027 = 0x004D = 77である点に注目するとよりわかりやすいかもしれません)
対してOrdinalの場合ですが、"coop"と"co-op"の3文字目を比較すると''o''(U+006F)と''-''(U+002D)であるため"''coop''>''co-op''"という結果になります。 同様に、"cant"と"can't"の3文字目は''t''(U+0074)と'(U+0027)であるため"''cant''>''can't''"という結果になります。 (この結果も、0x006F - 0x002D = 0x0042 = 66、0x0074-0x0027 = 0x004D = 77である点に注目するとよりわかりやすいかもしれません)
 

        

        
+
CurrentCultureIgnoreCaseとOrdinalIgnoreCaseの場合もこれと同様の動作となります。
+

          
+

          
+
***StringComparisonの使い分け
+
StringComparisonの各値の動作を再掲すると次のようになっています。
+

          
+
|*StringComparisonの値と文字列比較時の動作
+
|~StringComparisonの値|~文字列比較時の動作|h
+
|CurrentCulture&br;CurrentCultureIgnoreCase|現在のカルチャの並べ替え規則に基づいて比較する|
+
|InvariantCulture&br;InvariantCultureIgnoreCase|インバリアントカルチャの並べ替え規則に基づいて比較する|
+
|Ordinal&br;OrdinalIgnoreCase|文字列の各文字を数値(Unicode序数、Unicode ordinal)=コードポイントで比較する|
+

          
+
CurrentCultureは設定されているカルチャによって結果が変わる可能性がありますが、その結果はカルチャに合わせた適切な文字列比較動作となっています。 したがって、UIで表示されるような文字列に対して使用するのが想定される主な適用範囲となります。
+

          
+
一方、InvariantCultureやOrdinalはカルチャによらず一定の結果となります。 したがって、実行環境によって結果が変わることが望ましくない部分、例えば内部のソートや比較処理など、ロジック部分での文字列操作が想定される主な適用範囲となります。
+

          
+
CurrentCultureやInvariantCultureでは、各文字の持つ意味的な側面(句読点や記号の扱い、アクセント記号の有無など)を考慮した比較となるため、あいまいな比較(あるいは'''自然な'''比較)でも構わない場合はこちらを使うことができます。 一方、バイト単位での比較のように、各文字の持つ意味的な側面を排除して、すべての文字を単なる数値として等しく扱いたい場合はOrdinalを使うのが望ましいと言えます。
+

          
+

          
 
**StringComparerクラス [#StringComparer]
**StringComparerクラス [#StringComparer]
 
&msdn(netfx,type,System.StringComparer){StringComparerクラス};は文字列比較の実装を提供するクラスです。 IComparer<string>、IEqualityComparer<string>を実装しているため、これらのインターフェイスを使った文字列比較を行う際は、このクラスのインスタンスを使うことが出来ます。 また、[[StringComparison>#StringComparison]]と対応する実装を提供する静的プロパティも用意されています。
&msdn(netfx,type,System.StringComparer){StringComparerクラス};は文字列比較の実装を提供するクラスです。 IComparer<string>、IEqualityComparer<string>を実装しているため、これらのインターフェイスを使った文字列比較を行う際は、このクラスのインスタンスを使うことが出来ます。 また、[[StringComparison>#StringComparison]]と対応する実装を提供する静的プロパティも用意されています。
 

        

        
542,10 389,6
 
|StringComparer.Ordinal|StringComparison.Ordinal|
|StringComparer.Ordinal|StringComparison.Ordinal|
 
|StringComparer.OrdinalIgnoreCase|StringComparison.OrdinalIgnoreCase|
|StringComparer.OrdinalIgnoreCase|StringComparison.OrdinalIgnoreCase|
 

        

        
+
#remarks
+
IComparer<T>インターフェイスの詳細や使用例・実装例については[[programming/netfx/comparison/0_comparison]]、IEqualityComparer<T>インターフェイスについては[[programming/netfx/comparison/1_equation]]を参照してください。
+
#remarks-end
+

          
 
***StringComparerとソート
***StringComparerとソート
 
例として、StringComparerとList<string>.Sortメソッドを使って、その結果の違いを見てみます。 List<string.Sortメソッドは並べ替え時の比較を行うためのIComparer<string>を引数にとるため、StringComparerを使用することが出来ます。
例として、StringComparerとList<string>.Sortメソッドを使って、その結果の違いを見てみます。 List<string.Sortメソッドは並べ替え時の比較を行うためのIComparer<string>を引数にとるため、StringComparerを使用することが出来ます。
 

        

        
757,7 600,22
 
*CompareOptions列挙型 [#CompareOptions]
*CompareOptions列挙型 [#CompareOptions]
 
&msdn(netfx,type,System.Globalization.CompareOptions){CompareOptions列挙型};も、StringComparisonと同じく文字列比較の際の動作を指定するための列挙型ですが、StringComparisonよりも具体的な指定を行うことが出来ます。 StringComparisonの場合と異なり、Stringクラスでは&msdn(netfx,member,System.String.Compare){Compareメソッド};のみがCompareOptionsを指定した比較をサポートしています。
&msdn(netfx,type,System.Globalization.CompareOptions){CompareOptions列挙型};も、StringComparisonと同じく文字列比較の際の動作を指定するための列挙型ですが、StringComparisonよりも具体的な指定を行うことが出来ます。 StringComparisonの場合と異なり、Stringクラスでは&msdn(netfx,member,System.String.Compare){Compareメソッド};のみがCompareOptionsを指定した比較をサポートしています。
 

        

        
~
以下はString.CompareメソッドにCompareOptionsを指定して文字列の比較を行う例です。
CompareOptionsを指定する場合は、次の値を組み合わせて指定できます。
-
|*CompareOptions
-
|~CompareOptionsの値|~文字列比較時の動作|h
-
|None|デフォルトの動作で比較する|
-
|IgnoreCase|大文字小文字の違いを無視して比較する|
-
|IgnoreKanaType|ひらがなとカタカナの違いを無視して比較する|
-
|IgnoreWidth|全角と半角の違いを無視して比較する|
-
|IgnoreNonSpace|濁点付きの文字、囲み文字や発音記号など、基本となる文字と修飾記号の組み合わせになる文字について、'''非スペーシング組み合わせ文字'''となる修飾記号を無視して比較する|
-
|IgnoreSymbols|空白文字・句読点・その他の記号を無視して比較する|
-
|StringSort|ハイフン・アポストロフィが英数字や他の記号よりも前になるように比較する|
-
|Ordinal|文字列の各文字を数値(Unicode序数、Unicode ordinal)=コードポイントで比較する&br;(StringComparison.Ordinalと同じ)|
-
|OrdinalIgnoreCase|文字列の各文字を数値(Unicode序数、Unicode ordinal)=コードポイントで比較する&br;大文字小文字の違いは無視する&br;(StringComparison.OrdinalIgnoreCaseと同じ)|
-

          
-
なお、OrdinalとOrdinalIgnoreCaseは他の値とは組み合わせることはできないため、単独で使用する必要があります。 また、CompareOptionsを指定する場合は、CompareOptionsと合わせてCultureInfoも指定する必要があります。
-

          
-
以下はString.CompareメソッドにCompareOptionsを指定する例です。
 

        

        
 
#tabpage(codelang=cs)
#tabpage(codelang=cs)
 
#code{{
#code{{
794,42 652,7
 
CompareOptions.IgnoreCase : 0
CompareOptions.IgnoreCase : 0
 
}}
}}
 

        

        
~
CompareOptionsを指定する場合は、次の値を組み合わせて指定することができます。
**IgnoreCase, IgnoreKanaType, IgnoreWidth
+

          
+
|*CompareOptions
+
|~CompareOptionsの値|~文字列比較時の動作|~解説|h
+
|None|デフォルトの動作で比較する|-|
+
|IgnoreCase|大文字小文字の違いを無視して比較する|[[解説へ>#CompareOptions.IgnoreCase]]|
+
|IgnoreKanaType|ひらがなとカタカナの違いを無視して比較する|~|
+
|IgnoreWidth|全角と半角の違いを無視して比較する|~|
+
|IgnoreNonSpace|濁点付きの文字、囲み文字や発音記号など、基本となる文字と修飾記号の組み合わせになる文字について、'''非スペーシング組み合わせ文字'''となる修飾記号を無視して比較する&br;(例として、``"えと"``と``"えど"``、``"cafe"``と``"café"``、``"1"``と``"①"``は同じ文字列として扱われる)|[[解説へ>#CompareOptions.IgnoreNonSpace]]|
+
|IgnoreSymbols|空白文字・句読点・その他の記号を無視して比較する&br;(例として、``"Hello, world!"``と``"Helloworld"``は同じ文字列として扱われる)|[[解説へ>#CompareOptions.IgnoreSymbols]]|
+
|StringSort|ハイフン・アポストロフィが英数字や他の記号よりも前になるように比較する&br;(例として、``"can't"``は``"cant"``より''小さい''として扱われる)|[[解説へ>#CompareOptions.StringSort]]|
+
|Ordinal|文字列の各文字を数値(Unicode序数、Unicode ordinal)=コードポイントで比較する|([[StringComparison.Ordinal>#StringComparison]]と同じ)|
+
|OrdinalIgnoreCase|文字列の各文字を数値(Unicode序数、Unicode ordinal)=コードポイントで比較する&br;大文字小文字の違いは無視する|([[StringComparison.OrdinalIgnoreCase>#StringComparison]]と同じ)|
+

          
+
個々のオプションと動作の詳細については追って解説します。 なお、OrdinalおよびOrdinalIgnoreCaseは他の値とは組み合わせることはできないため、単独で使用する必要があります。
+

          
+
ソートやDictionaryのキー比較にCompareOptionsを使用する方法については[[#sort_with_CompareOptions]]で追って解説します。
+

          
+
**CompareOptionsとCultureInfo
+
String.CompareメソッドでCompareOptionsを指定する場合、必ずCultureInfoも指定する必要があります。 引数で指定されたCultureInfoでの定義にしたがった比較に加えてCompareOptionsで指定した比較オプションが適用されるため、例えCompareOptionsが同じでもCultureInfoが異なれば結果も異なる場合があります。
+

          
+
#remarks
+
なお、OrdinalとOrdinalIgnoreCaseはCultureInfoでの定義ではなくコードポイントでの比較が行われるため、指定したCultureInfoによらず結果は一定です。
+
#remarks-end
+

          
+
一方、[[StringComparison>#StringComparison]]では現在のカルチャまたはインバリアントカルチャのいずれかのみが指定できますが、String.CompareメソッドでCompareOptionsを指定する場合ではインバリアントカルチャを含む任意のカルチャを指定することができます。
+

          
+
CompareOptionsとCultureInfoの組み合わせとStringComparisonの対応については[[#CompareOptions_vs_StringComparison]]で解説します。
+

          
+
#remarks
+
CultureInfoクラスおよびカルチャ情報については[[programming/netfx/locale/0_abstract]]を参照してください。
+
#remarks-end
+

          
+
**CompareOptionsの値と文字列比較の動作
+

          
+
***IgnoreCase, IgnoreKanaType, IgnoreWidth [#CompareOptions.IgnoreCase]
 
IgnoreCase, IgnoreKanaType, IgnoreWidthはそれぞれ大文字小文字、ひらがなとカタカナ、全角と半角を区別しないで比較するように指定します。 これらの値や他の値と組み合わせて使用することも出来ます。
IgnoreCase, IgnoreKanaType, IgnoreWidthはそれぞれ大文字小文字、ひらがなとカタカナ、全角と半角を区別しないで比較するように指定します。 これらの値や他の値と組み合わせて使用することも出来ます。
 

        

        
 
#tabpage(codelang=cs)
#tabpage(codelang=cs)
915,7 738,7
 
アイウエオ あいうえお :  0 (IgnoreKanaType, IgnoreWidth)
アイウエオ あいうえお :  0 (IgnoreKanaType, IgnoreWidth)
 
}}
}}
 

        

        
~
***IgnoreNonSpace [#CompareOptions.IgnoreNonSpace]
**IgnoreNonSpace
 
IgnoreNonSpaceは、濁点付きの文字、囲み文字や発音記号など、基本となる文字と修飾記号の組み合わせになる文字について、その組み合わせを無視して比較するように指定します。 これらの値や他の値と組み合わせて使用することも出来ます。 &msdn(netfx,type,System.Globalization.CompareOptions){CompareOptions.IgnoreNonSpace};の解説では、
IgnoreNonSpaceは、濁点付きの文字、囲み文字や発音記号など、基本となる文字と修飾記号の組み合わせになる文字について、その組み合わせを無視して比較するように指定します。 これらの値や他の値と組み合わせて使用することも出来ます。 &msdn(netfx,type,System.Globalization.CompareOptions){CompareOptions.IgnoreNonSpace};の解説では、
 
>文字列比較で、発音区別符など、非スペーシング組み合わせ文字を無視するように指定します。Unicode 標準は、新しい文字を生成するために基本文字と組み合わせられる文字を組み合わせ文字として定義しています。非スペーシング組み合わせ文字は、表示されるときに文字間隔用の領域は確保しません。
>文字列比較で、発音区別符など、非スペーシング組み合わせ文字を無視するように指定します。Unicode 標準は、新しい文字を生成するために基本文字と組み合わせられる文字を組み合わせ文字として定義しています。非スペーシング組み合わせ文字は、表示されるときに文字間隔用の領域は確保しません。
 
とされています。 '''非スペーシング組み合わせ文字'''とは、Unicodeのカテゴリ'Mark, Nonspacing' [Mn]のことで、これに該当する文字は比較の際に無視されることになります。
とされています。 '''非スペーシング組み合わせ文字'''とは、Unicodeのカテゴリ'Mark, Nonspacing' [Mn]のことで、これに該当する文字は比較の際に無視されることになります。
1082,10 905,10
 
:"1"と"①"&br;"1"と"①"|''&#x2460;''(U+2460 CIRCLED DIGIT ONE)は''&#x0031;''(U+0031 DIGIT ONE)とほぼ等価とされているため、IgnoreNonSpaceの場合"1"と"①"は同じであると判断されます。
:"1"と"①"&br;"1"と"①"|''&#x2460;''(U+2460 CIRCLED DIGIT ONE)は''&#x0031;''(U+0031 DIGIT ONE)とほぼ等価とされているため、IgnoreNonSpaceの場合"1"と"①"は同じであると判断されます。
 
また、''&#xFF11;''(U+FF11 FULLWIDTH DIGIT ONE)は''&#x0031;''(U+0031 DIGIT ONE)と全角半角の関係にあるため、IgnoreNonSpace+IgnoreWidthの場合"1"と"①"は同じであると判断されます。
また、''&#xFF11;''(U+FF11 FULLWIDTH DIGIT ONE)は''&#x0031;''(U+0031 DIGIT ONE)と全角半角の関係にあるため、IgnoreNonSpace+IgnoreWidthの場合"1"と"①"は同じであると判断されます。
 

        

        
~
***IgnoreSymbols [#CompareOptions.IgnoreSymbols]
**IgnoreSymbol
 
(このドキュメントは未整理です)
(このドキュメントは未整理です)
 

        

        
~
IgnoreSymbolsは、空白文字、句読点等の記号を無視して比較するように指定します。 これらの値や他の値と組み合わせて使用することも出来ます。 &msdn(netfx,type,System.Globalization.CompareOptions){CompareOptions.IgnoreSymbols};の解説では、
IgnoreSymbolは、空白文字、句読点等の記号を無視して比較するように指定します。 これらの値や他の値と組み合わせて使用することも出来ます。 &msdn(netfx,type,System.Globalization.CompareOptions){CompareOptions.IgnoreSymbol};の解説では、
 
>文字列比較において、空白文字、句読点、通貨記号、パーセント記号、算術記号、アンパサンドなどの記号を無視することを示します。 
>文字列比較において、空白文字、句読点、通貨記号、パーセント記号、算術記号、アンパサンドなどの記号を無視することを示します。 
 
とされているものの、具体的にどの記号が無視される対象なのかは明記されていないようです。 また、.NET FrameworkとMonoでも実行結果は異なるようです。
とされているものの、具体的にどの記号が無視される対象なのかは明記されていないようです。 また、.NET FrameworkとMonoでも実行結果は異なるようです。
 

        

        
1186,7 1009,7
 
}}
}}
 
#tabpage-end
#tabpage-end
 

        

        
~
***StringSort [#CompareOptions.StringSort]
**StringSort
 
(このドキュメントは未整理です)
(このドキュメントは未整理です)
 

        

        
 
StringSortは、ハイフン・アポストロフィが英数字や他の記号よりも前になるように比較するように指定します。 これらの値や他の値と組み合わせて使用することも出来ます。 &msdn(netfx,type,System.Globalization.CompareOptions){CompareOptions.StringSort};の解説では、
StringSortは、ハイフン・アポストロフィが英数字や他の記号よりも前になるように比較するように指定します。 これらの値や他の値と組み合わせて使用することも出来ます。 &msdn(netfx,type,System.Globalization.CompareOptions){CompareOptions.StringSort};の解説では、
1334,7 1157,7
 
}}
}}
 
#tabpage-end
#tabpage-end
 

        

        
~
***CompareOptionsとStringComparison [#CompareOptions_vs_StringComparison]
**CompareOptionsとStringComparison
 
StringComparisonを指定した場合と同じ比較処理をCompareOptionsでも行うことが出来ます。 以下の表は、StringComparisonの値と、対応するCompareOptionsとCultureInfoの値の組み合わせです。
StringComparisonを指定した場合と同じ比較処理をCompareOptionsでも行うことが出来ます。 以下の表は、StringComparisonの値と、対応するCompareOptionsとCultureInfoの値の組み合わせです。
 

        

        
 
|*StringComparisonと等価なCompareOptionsとCultureInfoの組み合わせ
|*StringComparisonと等価なCompareOptionsとCultureInfoの組み合わせ
1435,14 1258,10
 
Compare CompareOptions.None (Invariant)   : 1
Compare CompareOptions.None (Invariant)   : 1
 
}}
}}
 

        

        
~
#remarks
**CompareOptionsと部分文字列の検索・一致
~
それぞれの結果の違いに関しては、[[#StringComparison.CurrentCulture_vs_StringComparison.InvariantCulture]]および[[#StringComparison.CurrentCulture_vs_StringComparison.Ordinal]]もあわせて参照してください。
String.Compareメソッドとは異なり、String.IndexOfなど部分文字列の検索と一致を検証するメソッドではStringComparisonを引数にとるオーバーロードは用意されていますが、CompareOptionsをとるオーバーロードは用意されていません。 CompareOptionsを使ってこれらの処理を行うには、&msdn(netfx,type,System.Globalization.CompareInfo){CompareInfoクラス};のメソッドを使う必要があります。
+
#remarks-end
+

          
+
**CompareOptionsと部分文字列の探索・一致
+
String.Compareメソッドとは異なり、String.IndexOfなど部分文字列の探索と一致を検証するメソッドではStringComparisonを引数にとるオーバーロードは用意されていますが、CompareOptionsをとるオーバーロードは用意されていません。 CompareOptionsを使ってこれらの処理を行うには、&msdn(netfx,type,System.Globalization.CompareInfo){CompareInfoクラス};のメソッドを使う必要があります。
 

        

        
~
|*部分文字列の探索・一致を行うメソッド
|*部分文字列の検索・一致を行うメソッド
 
|~Stringクラスのメソッド|~代用できるCompareInfoクラスのメソッド|h
|~Stringクラスのメソッド|~代用できるCompareInfoクラスのメソッド|h
 
|&msdn(netfx,member,System.String.IndexOf){String.IndexOfメソッド};|&msdn(netfx,member,System.Globalization.CompareInfo.IndexOf){CompareInfo.IndexOfメソッド};|
|&msdn(netfx,member,System.String.IndexOf){String.IndexOfメソッド};|&msdn(netfx,member,System.Globalization.CompareInfo.IndexOf){CompareInfo.IndexOfメソッド};|
 
|&msdn(netfx,member,System.String.LastIndexOf){String.LastIndexOfメソッド};|&msdn(netfx,member,System.Globalization.CompareInfo.LastIndexOf){CompareInfo.LastIndexOfメソッド};|
|&msdn(netfx,member,System.String.LastIndexOf){String.LastIndexOfメソッド};|&msdn(netfx,member,System.Globalization.CompareInfo.LastIndexOf){CompareInfo.LastIndexOfメソッド};|
1450,9 1269,7
 
|&msdn(netfx,member,System.String.EndsWith){String.EndsWithメソッド};|&msdn(netfx,member,System.Globalization.CompareInfo.IsSuffix){CompareInfo.IsSuffixメソッド};|
|&msdn(netfx,member,System.String.EndsWith){String.EndsWithメソッド};|&msdn(netfx,member,System.Globalization.CompareInfo.IsSuffix){CompareInfo.IsSuffixメソッド};|
 
|&msdn(netfx,member,System.String.Equals){String.Equalsメソッド};|(なし)|
|&msdn(netfx,member,System.String.Equals){String.Equalsメソッド};|(なし)|
 

        

        
~
なお、これらのメソッドで[[CompareOptions.StringSort>#CompareOptions.StringSort]]を指定することはできません。 指定した場合はArgumentExceptionがスローされます。
次の例は、CompareInfoクラスの各メソッドを使った部分文字列の検索と一致の例です。
+

          
+
次の例は、CompareInfoクラスの各メソッドを使った部分文字列の探索と一致の例です。
 

        

        
 
#tabpage(codelang=cs)
#tabpage(codelang=cs)
 
#code{{
#code{{
1585,27 1402,24
 
True
True
 
}}
}}
 

        

        
~
**CompareOptionsとソート [#sort_with_CompareOptions]
**CompareOptionsとソート
 
StringComparisonとは異なり、CompareOptionsに対応したIComparer<string>、IEqualityComparer<string>を提供するクラスはないため、自前で実装する必要があります。 例えば、キーのひらがなとカタカナの違いを無視するDictionary<string, string>を作成するには次のようにします。
StringComparisonとは異なり、CompareOptionsに対応したIComparer<string>、IEqualityComparer<string>を提供するクラスはないため、自前で実装する必要があります。 例えば、キーのひらがなとカタカナの違いを無視するDictionary<string, string>を作成するには次のようにします。
 

        

        
~
#tabpage(codelang=cs,container-title=Dictionaryのキー比較にCompareOptionsを使用する例)
#tabpage(codelang=cs)
 
#code{{
#code{{
 
using System;
using System;
 
using System.Collections.Generic;
using System.Collections.Generic;
 
using System.Globalization;
using System.Globalization;
 

        

        
+
// ひらがな・カタカナの違いを無視するIEqualityComparer<string>
 
class IgnoreKanaTypeComparer : EqualityComparer<string>
class IgnoreKanaTypeComparer : EqualityComparer<string>
 
{
{
 
  public override bool Equals(string x, string y)
  public override bool Equals(string x, string y)
 
  {
  {
+
    // CompareOptions.IgnoreKanaTypeを指定して2つの文字列が等しいか否かを判定する
 
    return String.Compare(x, y, CultureInfo.InvariantCulture, CompareOptions.IgnoreKanaType) == 0;
    return String.Compare(x, y, CultureInfo.InvariantCulture, CompareOptions.IgnoreKanaType) == 0;
 
  }
  }
 

        

        
 
  public override int GetHashCode(string s)
  public override int GetHashCode(string s)
 
  {
  {
+
    // 実装は省略
 
    return 0;
    return 0;
 
  }
  }
 
}
}
1614,14 1428,13
 
{
{
 
  static void Main()
  static void Main()
 
  {
  {
+
    // 独自に実装したIEqualityComparer<string>を指定してDictionaryを作成する
 
    Dictionary<string, string> dict = new Dictionary<string, string>(new IgnoreKanaTypeComparer());
    Dictionary<string, string> dict = new Dictionary<string, string>(new IgnoreKanaTypeComparer());
 

        

        
 
    dict["ほげ"] = "hoge";
    dict["ほげ"] = "hoge";
 
    dict["ぴよ"] = "piyo";
    dict["ぴよ"] = "piyo";
 
    dict["ふが"] = "fuga";
    dict["ふが"] = "fuga";
 

        

        
~
    dict["ピヨ"] = "PIYO"; // ひらがな・カタカナの違いは無視されるため、キー"ぴよ"の値が上書きされる
    dict["ピヨ"] = "PIYO";
 

        

        
 
    foreach (KeyValuePair<string, string> p in dict)
    foreach (KeyValuePair<string, string> p in dict)
 
    {
    {
1638,31 1451,27
 
Imports System.Collections.Generic
Imports System.Collections.Generic
 
Imports System.Globalization
Imports System.Globalization
 

        

        
+
' ひらがな・カタカナの違いを無視するIEqualityComparer(Of String)
 
Class IgnoreKanaTypeComparer
Class IgnoreKanaTypeComparer
 
  Inherits EqualityComparer(Of String)
  Inherits EqualityComparer(Of String)
 

        

        
 
  Public Overrides Function Equals(ByVal x As String, ByVal y As String) As Boolean
  Public Overrides Function Equals(ByVal x As String, ByVal y As String) As Boolean
+
    ' CompareOptions.IgnoreKanaTypeを指定して2つの文字列が等しいか否かを判定する
 
    Return String.Compare(x, y, CultureInfo.InvariantCulture, CompareOptions.IgnoreKanaType) = 0
    Return String.Compare(x, y, CultureInfo.InvariantCulture, CompareOptions.IgnoreKanaType) = 0
 
  End Function
  End Function
 

        

        
 
  Public Overrides Function GetHashCode(ByVal s As String) As Integer
  Public Overrides Function GetHashCode(ByVal s As String) As Integer
+
    ' 実装は省略
 
    Return 0
    Return 0
 
  End Function
  End Function
 
End Class
End Class
 

        

        
 
Class Sample
Class Sample
 
  Shared Sub Main()
  Shared Sub Main()
+
    ' 独自に実装したIEqualityComparer(Of String)を指定してDictionaryを作成する
 
    Dim dict As New Dictionary(Of String, String)(New IgnoreKanaTypeComparer())
    Dim dict As New Dictionary(Of String, String)(New IgnoreKanaTypeComparer())
 

        

        
 
    dict("ほげ") = "hoge"
    dict("ほげ") = "hoge"
 
    dict("ぴよ") = "piyo"
    dict("ぴよ") = "piyo"
 
    dict("ふが") = "fuga"
    dict("ふが") = "fuga"
 

        

        
~
    dict("ピヨ") = "PIYO" ' ひらがな・カタカナの違いは無視されるため、キー"ぴよ"の値が上書きされる
    dict("ピヨ") = "PIYO"
 

        

        
 
    For Each p As KeyValuePair(Of String, String) In dict
    For Each p As KeyValuePair(Of String, String) In dict
 
      Console.WriteLine("{0} => {1}", p.Key, p.Value)
      Console.WriteLine("{0} => {1}", p.Key, p.Value)
1683,13 1492,9
 

        

        
 
この例では、&msdn(netfx,type,System.Collections.Generic.EqualityComparer`1){EqualityComparer<string>クラス};を継承することでIEqualityComparer<string>インターフェイスを実装しています。 また、GetHashCodeメソッドの実装は省略していますが、オブジェクトのハッシュ値が使用される場合は適切に実装する必要があります。
この例では、&msdn(netfx,type,System.Collections.Generic.EqualityComparer`1){EqualityComparer<string>クラス};を継承することでIEqualityComparer<string>インターフェイスを実装しています。 また、GetHashCodeメソッドの実装は省略していますが、オブジェクトのハッシュ値が使用される場合は適切に実装する必要があります。
 

        

        
~
#remarks
また、Array.SortやList<string>.Sortの場合は、IComparerを用意しなくてもComparison<string>に適合するメソッドがあれば良いので、次のようにできます。
+
EqualityComparer<T>についての解説や実装例については[[programming/netfx/comparison/1_equation#EqualityComparer]]を参照してください。
+
#remarks-end
 

        

        
~
また、List<string>.SortやArray.Sortの場合は、IComparerを用意しなくても&msdn(netfx,type,System.Comparison`1){Comparison<string>デリゲート};に適合するメソッドがあれば良いので、次のようにできます。
#tabpage(codelang=cs)
+

          
+
#tabpage(codelang=cs,container-title=List<string>.SortでCompareOptionsを使用する例)
 
#code{{
#code{{
 
using System;
using System;
 
using System.Collections.Generic;
using System.Collections.Generic;
1697,7 1502,6
 

        

        
 
class Sample
class Sample
 
{
{
+
  // 文字列の比較を行うメソッド
 
  static int CompareIgnoreWidth(string x, string y)
  static int CompareIgnoreWidth(string x, string y)
 
  {
  {
 
    return String.Compare(x, y, CultureInfo.InvariantCulture, CompareOptions.IgnoreWidth);
    return String.Compare(x, y, CultureInfo.InvariantCulture, CompareOptions.IgnoreWidth);
1705,7 1509,10
 

        

        
 
  static void Main()
  static void Main()
 
  {
  {
~
    List<string> wordList = new List<string>(new string[] {"foo", "Foo", "foo", "FOO", "FOO", "Foo"});
    string[] wordArray = new string[] {"foo", "Foo", "foo", "FOO", "FOO", "Foo"};
-
    List<string> wordList = new List<string>(wordArray);
-

          
-
    Console.WriteLine("List.Sort");
 

        

        
 
    Console.WriteLine("before sort                    : {0}", String.Join(", ", wordList.ToArray()));
    Console.WriteLine("before sort                    : {0}", String.Join(", ", wordList.ToArray()));
 

        

        
1720,66 1527,8
 
    wordList.Sort(StringComparer.Ordinal);
    wordList.Sort(StringComparer.Ordinal);
 

        

        
 
    Console.WriteLine("StringComparer.Ordinal         : {0}", String.Join(", ", wordList.ToArray()));
    Console.WriteLine("StringComparer.Ordinal         : {0}", String.Join(", ", wordList.ToArray()));
+
  }
+
}
+
}}
+
#tabpage(codelang=vb)
+
#code{{
+
Imports System
+
Imports System.Collections.Generic
+
Imports System.Globalization
+

          
+
Class Sample
+
  ' 文字列の比較を行うメソッド
+
  Shared Function CompareIgnoreWidth(ByVal x As String, ByVal y As String) As Integer
+
    Return String.Compare(x, y, CultureInfo.InvariantCulture, CompareOptions.IgnoreWidth)
+
  End Function
+

          
+
  Shared Sub Main()
+
    Dim wordList As New List(Of String)(New String() {"foo", "Foo", "foo", "FOO", "FOO", "Foo"})
+

          
+
    Console.WriteLine("before sort                    : {0}", String.Join(", ", wordList.ToArray()))
+

          
+
    wordList.Sort(AddressOf CompareIgnoreWidth)
+

          
+
    Console.WriteLine("CompareIgnoreWidth             : {0}", String.Join(", ", wordList.ToArray()))
+

          
+
    wordList.Sort(StringComparer.InvariantCulture)
+

          
+
    Console.WriteLine("StringComparer.InvariantCulture: {0}", String.Join(", ", wordList.ToArray()))
+

          
+
    wordList.Sort(StringComparer.Ordinal)
+

          
+
    Console.WriteLine("StringComparer.Ordinal         : {0}", String.Join(", ", wordList.ToArray()))
+
  End Sub
+
End Class
+
}}
+
#tabpage-end
+

          
+
#prompt{{
+
before sort                    : foo, Foo, foo, FOO, FOO, Foo
+
CompareIgnoreWidth             : foo, foo, Foo, Foo, FOO, FOO
+
StringComparer.InvariantCulture: foo, foo, Foo, FOO, Foo, FOO
+
StringComparer.Ordinal         : FOO, Foo, foo, FOO, Foo, foo
+
}}
+

          
+
#tabpage(codelang=cs,container-title=Array.SortでCompareOptionsを使用する例)
+
#code{{
+
using System;
+
using System.Collections.Generic;
+
using System.Globalization;
 

        

        
~
class Sample
    Console.WriteLine("Array.Sort");
+
{
+
  // 文字列の比較を行うメソッド
+
  static int CompareIgnoreWidth(string x, string y)
+
  {
+
    return String.Compare(x, y, CultureInfo.InvariantCulture, CompareOptions.IgnoreWidth);
+
  }
+

          
+
  static void Main()
+
  {
+
    string[] wordArray = new string[] {"foo", "Foo", "foo", "FOO", "FOO", "Foo"};
 

        

        
 
    Console.WriteLine("before sort                    : {0}", String.Join(", ", wordArray));
    Console.WriteLine("before sort                    : {0}", String.Join(", ", wordArray));
 

        

        
1804,13 1553,31
 
Imports System.Globalization
Imports System.Globalization
 

        

        
 
Class Sample
Class Sample
+
  ' 文字列の比較を行うメソッド
 
  Shared Function CompareIgnoreWidth(ByVal x As String, ByVal y As String) As Integer
  Shared Function CompareIgnoreWidth(ByVal x As String, ByVal y As String) As Integer
 
    Return String.Compare(x, y, CultureInfo.InvariantCulture, CompareOptions.IgnoreWidth)
    Return String.Compare(x, y, CultureInfo.InvariantCulture, CompareOptions.IgnoreWidth)
 
  End Function
  End Function
 

        

        
 
  Shared Sub Main()
  Shared Sub Main()
 
    Dim wordArray As String() = New String() {"foo", "Foo", "foo", "FOO", "FOO", "Foo"}
    Dim wordArray As String() = New String() {"foo", "Foo", "foo", "FOO", "FOO", "Foo"}
-
    Dim wordList As New List(Of String)(wordArray)
-

          
-
    Console.WriteLine("List.Sort")
-

          
-
    Console.WriteLine("before sort                    : {0}", String.Join(", ", wordList.ToArray()))
-

          
-
    wordList.Sort(AddressOf CompareIgnoreWidth)
-

          
-
    Console.WriteLine("CompareIgnoreWidth             : {0}", String.Join(", ", wordList.ToArray()))
-

          
-
    wordList.Sort(StringComparer.InvariantCulture)
-

          
-
    Console.WriteLine("StringComparer.InvariantCulture: {0}", String.Join(", ", wordList.ToArray()))
-

          
-
    wordList.Sort(StringComparer.Ordinal)
-

          
-
    Console.WriteLine("StringComparer.Ordinal         : {0}", String.Join(", ", wordList.ToArray()))
-

          
-
    Console.WriteLine("Array.Sort")
 

        

        
 
    Console.WriteLine("before sort                    : {0}", String.Join(", ", wordArray))
    Console.WriteLine("before sort                    : {0}", String.Join(", ", wordArray))
 

        

        
1836,11 1603,12
 
CompareIgnoreWidth             : foo, foo, Foo, Foo, FOO, FOO
CompareIgnoreWidth             : foo, foo, Foo, Foo, FOO, FOO
 
StringComparer.InvariantCulture: foo, foo, Foo, FOO, Foo, FOO
StringComparer.InvariantCulture: foo, foo, Foo, FOO, Foo, FOO
 
StringComparer.Ordinal         : FOO, Foo, foo, FOO, Foo, foo
StringComparer.Ordinal         : FOO, Foo, foo, FOO, Foo, foo
-
Array.Sort
-
before sort                    : foo, Foo, foo, FOO, FOO, Foo
-
CompareIgnoreWidth             : foo, foo, Foo, Foo, FOO, FOO
-
StringComparer.InvariantCulture: foo, foo, Foo, FOO, Foo, FOO
-
StringComparer.Ordinal         : FOO, Foo, foo, FOO, Foo, foo
 
}}
}}
 

        

        
+
#remarks
+
Comparison<T>デリゲートについては[[programming/netfx/comparison/0_comparison#Comparison]]を参照してください。
+
#remarks-end
+

          
 
#navi(..)
#navi(..)
 

        

        

programming/netfx/string/4_stringbuilder/index.wiki.txt

current previous
5,7 5,7
 

        

        
 
#navi(..)
#navi(..)
 

        

        
~
ここでは&msdn(netfx,type,System.Text.StringBuilder){StringBuilderクラス};ついて見ていきます。 StringBuilderクラスを用いることにより、直接文字列を操作するよりも効率的に文字列の加工・編集を行うことができます。
ここでは&msdn(netfx,type,System.Text.StringBuilder){StringBuilderクラス};ついて見ていきます。 StringBuilderクラスを用いることで、効率的に文字列の加工・編集を行うことができます。
 

        

        
 
#relevantdocs
#relevantdocs
 

        

        
18,112 18,51
 

        

        
 
#adunit
#adunit
 

        

        
~
*StringBuilderクラスの特徴
*StringBuilderクラスの特徴とStringクラスとの違い
~
.NET Frameworkの&msdn(netfx,type,System.String){Stringクラス};はインスタンスの持つ値を変更できないという性質を持つ'''不変な'''型です。 Stringクラスの文字列操作ではインスタンス自体が持っている値(=文字列)が変わることは無く、操作の度に結果が格納された新しい文字列のインスタンスが生成されます。
.NET FrameworkのStringクラスはインスタンスの持つ値を変更できないという性質を持つ'''不変な'''型です。 Stringクラスの文字列操作では値が変わることは無く、操作の度に新しい文字列のインスタンスが生成されます。
 

        

        
~
一方、&msdn(netfx,type,System.Text.StringBuilder){StringBuilderクラス};は内部にChar配列のバッファを保持し、文字列操作によってインスタンスの持つ値(=文字列)が変わる'''可変な'''型です。 StringBuilderクラスの文字列操作では、操作の際にバッファの内容のみが変更され、新しい文字列のインスタンスは生成されません。
一方、&msdn(netfx,type,System.Text.StringBuilder){StringBuilderクラス};は内部にChar配列のバッファを保持し、文字列操作によってインスタンスの持つ値が変わる'''可変な'''型です。 StringBuilderクラスの文字列操作では、操作の際にバッファの内容は変更されますが、新しい文字列のインスタンスは生成されません。 文字列の挿入・削除・置換などの操作を繰り返す場合は、StringBuilderクラスを用いて行った方が適しています。
 

        

        
~
このような特徴から、文字列の連結・挿入・削除・置換といった加工・編集を繰り返し行う操作の場合は、StringBuilderクラスを用いて行った方が適しています。 (実際にどの程度パフォーマンスに差が出るかは[[#performance]]で検証しています。)
詳細な使い方は後述するとして、まずはStringクラスとStringBuilderクラスで同じ操作を行う場合の違いを見ておきます。
 

        

        
~
一方でStringBuilderクラスにはStartsWith・IndexOf・Equalsといった文字列の探索・比較を行うメソッドは用意されていません。 探索・比較の目的には[[Stringクラスのメソッド>programming/netfx/string/2_1_comparison]]や[[Regexクラス>programming/netfx/regex/0_abstract]]を使用します。
#tabpage(codelang=cs)
+

          
+
*StringBuilderクラスとStringクラスの違い
+
まずはStringBuilderクラスとStringクラスで同じ操作を行う場合の違いを見ておきます。 詳細な使い方は後述します。
+

          
+
#column
+

          
+
#tabpage(codelang=cs,container-title=Stringクラスでの文字列操作)
 
#code{{
#code{{
 
using System;
using System;
~

          
using System.Text;
 

        

        
 
class Sample
class Sample
 
{
{
 
  static void Main()
  static void Main()
 
  {
  {
+
    // インスタンスの作成
 
    string s = "The quick brown fox jumps over the lazy dog";
    string s = "The quick brown fox jumps over the lazy dog";
-
    StringBuilder sb = new StringBuilder("The quick brown fox jumps over the lazy dog");
 

        

        
~
    Console.WriteLine(s);
    Console.WriteLine("String       : {0}", s);
-
    Console.WriteLine("StringBuilder: {0}", sb);
 

        

        
~
    // 末尾の8文字を削除する
    // 最後の8文字を削除
 
    s = s.Remove(s.Length - 8, 8);
    s = s.Remove(s.Length - 8, 8);
-
    sb.Remove(sb.Length - 8, 8);
 

        

        
~
    Console.WriteLine(s);
    Console.WriteLine("Remove");
-
    Console.WriteLine("String       : {0}", s);
-
    Console.WriteLine("StringBuilder: {0}", sb);
 

        

        
~
    // 文字列を末尾に追加する
    // 文字列を追加
 
    s = s + "silliy dog";
    s = s + "silliy dog";
-
    sb.Append("silliy dog");
 

        

        
~
    Console.WriteLine(s);
    Console.WriteLine("Append");
-
    Console.WriteLine("String       : {0}", s);
-
    Console.WriteLine("StringBuilder: {0}", sb);
 

        

        
~
    // 文字列を置換する
    // 文字列を置換
 
    s = s.Replace("The quick", "the clever");
    s = s.Replace("The quick", "the clever");
+

          
+
    Console.WriteLine(s);
+
  }
+
}
+
}}
+
#tabpage(codelang=vb)
+
#code{{
+
Imports System
+

          
+

          
+
Class Sample
+
  Shared Sub Main()
+
    ' インスタンスの作成
+
    Dim s As String = "The quick brown fox jumps over the lazy dog"
+

          
+
    Console.WriteLine(s)
+

          
+
    ' 末尾の8文字を削除する
+
    s = s.Remove(s.Length - 8, 8)
+

          
+
    Console.WriteLine(s)
+

          
+
    ' 文字列を末尾に追加する
+
    s = s + "silliy dog"
+

          
+
    Console.WriteLine(s)
+

          
+
    ' 文字列を置換する
+
    s = s.Replace("The quick", "the clever")
+

          
+
    Console.WriteLine(s)
+
  End Sub
+
End Class
+
}}
+
#tabpage-end
+

          
+
#column
+

          
+
#tabpage(codelang=cs,container-title=StringBuilderクラスでの文字列操作)
+
#code{{
+
using System;
+
using System.Text;
+

          
+
class Sample
+
{
+
  static void Main()
+
  {
+
    // インスタンスの作成
+
    StringBuilder sb = new StringBuilder("The quick brown fox jumps over the lazy dog");
+

          
+
    Console.WriteLine(sb);
+

          
+
    // 末尾の8文字を削除する
+
    sb.Remove(sb.Length - 8, 8);
+

          
+
    Console.WriteLine(sb);
+

          
+
    // 文字列を末尾に追加する
+
    sb.Append("silliy dog");
+

          
+
    Console.WriteLine(sb);
+

          
+
    // 文字列を置換する
 
    sb.Replace("The quick", "the clever");
    sb.Replace("The quick", "the clever");
 

        

        
~
    Console.WriteLine(sb);
    Console.WriteLine("Replace");
-
    Console.WriteLine("String       : {0}", s);
-
    Console.WriteLine("StringBuilder: {0}", sb);
 
  }
  }
 
}
}
 
}}
}}
134,44 73,57
 

        

        
 
Class Sample
Class Sample
 
  Shared Sub Main()
  Shared Sub Main()
~
    ' インスタンスの作成
    Dim s As String = "The quick brown fox jumps over the lazy dog"
 
    Dim sb As New StringBuilder("The quick brown fox jumps over the lazy dog")
    Dim sb As New StringBuilder("The quick brown fox jumps over the lazy dog")
 

        

        
~
    Console.WriteLine(sb)
    Console.WriteLine("String       : {0}", s)
-
    Console.WriteLine("StringBuilder: {0}", sb)
 

        

        
~
    ' 末尾の8文字を削除する
    ' 最後の8文字を削除
-
    s = s.Remove(s.Length - 8, 8)
 
    sb.Remove(sb.Length - 8, 8)
    sb.Remove(sb.Length - 8, 8)
 

        

        
~
    Console.WriteLine(sb)
    Console.WriteLine("Remove")
-
    Console.WriteLine("String       : {0}", s)
-
    Console.WriteLine("StringBuilder: {0}", sb)
 

        

        
~
    ' 文字列を末尾に追加する
    ' 文字列を追加
-
    s = s + "silliy dog"
 
    sb.Append("silliy dog")
    sb.Append("silliy dog")
 

        

        
~
    Console.WriteLine(sb)
    Console.WriteLine("Append")
-
    Console.WriteLine("String       : {0}", s)
-
    Console.WriteLine("StringBuilder: {0}", sb)
 

        

        
~
    ' 文字列を置換する
    ' 文字列を置換
-
    s = s.Replace("The quick", "the clever")
 
    sb.Replace("The quick", "the clever")
    sb.Replace("The quick", "the clever")
 

        

        
~
    Console.WriteLine(sb)
    Console.WriteLine("Replace")
-
    Console.WriteLine("String       : {0}", s)
-
    Console.WriteLine("StringBuilder: {0}", sb)
 
  End Sub
  End Sub
 
End Class
End Class
 
}}
}}
 
#tabpage-end
#tabpage-end
 

        

        
+
#column-end
+

          
 
#prompt(実行結果){{
#prompt(実行結果){{
~
The quick brown fox jumps over the lazy dog
String       : The quick brown fox jumps over the lazy dog
~
The quick brown fox jumps over the 
StringBuilder: The quick brown fox jumps over the lazy dog
~
The quick brown fox jumps over the silliy dog
Remove
~
the clever brown fox jumps over the silliy dog
String       : The quick brown fox jumps over the 
-
StringBuilder: The quick brown fox jumps over the 
-
Append
-
String       : The quick brown fox jumps over the silliy dog
-
StringBuilder: The quick brown fox jumps over the silliy dog
-
Replace
-
String       : the clever brown fox jumps over the silliy dog
-
StringBuilder: the clever brown fox jumps over the silliy dog
 
}}
}}
 

        

        
+
このように、Stringクラスの文字列操作ではその都度新しいインスタンスが生成されますが、StringBuilderクラスでは単一のインスタンスを使いまわして文字列操作を繰り返すことができます。
+

          
 
StringBuilderクラスの内容は、&msdn(netfx,member,System.Text.StringBuilder.ToString){StringBuilder.ToString};メソッドを使うことで通常の文字列として取得出来ます。
StringBuilderクラスの内容は、&msdn(netfx,member,System.Text.StringBuilder.ToString){StringBuilder.ToString};メソッドを使うことで通常の文字列として取得出来ます。
 

        

        
~
#tabpage(codelang=cs,container-title=StringBuilderからStringへの変換)
#tabpage(codelang=cs)
 
#code{{
#code{{
 
using System;
using System;
 
using System.Text;
using System.Text;
184,7 136,6
 

        

        
 
    sb.Append(" over the lazy dog");
    sb.Append(" over the lazy dog");
 

        

        
+
    // StringBuilderクラスが保持している文字列をStringとして取得する
 
    string s = sb.ToString();
    string s = sb.ToString();
 

        

        
 
    Console.WriteLine(s);
    Console.WriteLine(s);
202,7 153,6
 

        

        
 
    sb.Append(" over the lazy dog")
    sb.Append(" over the lazy dog")
 

        

        
+
    ' StringBuilderクラスが保持している文字列をStringとして取得する
 
    Dim s As String = sb.ToString()
    Dim s As String = sb.ToString()
 

        

        
 
    Console.WriteLine(s)
    Console.WriteLine(s)
215,12 165,13
 
The quick brown fox jumps over the lazy dog
The quick brown fox jumps over the lazy dog
 
}}
}}
 

        

        
~
*StringBuilderによる文字列操作
*StringBuilderと文字列操作
-
**文字列の結合 (Append, AppendLine, AppendFormat)
-
&msdn(netfx,member,System.Text.StringBuilder.Append){StringBuilder.Append};メソッドは、バッファに文字列を追加するメソッドで、String.Concatメソッドや加算演算子+による文字列の連結操作に相当します。
 

        

        
~
**文字列の追加 (Append, AppendLine)
また、&msdn(netfx,member,System.Text.StringBuilder.AppendLine){StringBuilder.AppendLine};メソッドは、バッファに文字列を追加する点はAppendメソッドと同様ですが、自動的に末尾に改行文字も追加されます。 改行文字は''常にEnvironment.NewLineが使われます''。 AppendLineメソッドに引数を指定しなかった場合は、改行文字のみが追加されます。
+
&msdn(netfx,member,System.Text.StringBuilder.Append){StringBuilder.Append};メソッドは、バッファの末尾に文字列を追加するメソッドで、[[String.Concatメソッド>programming/netfx/string/1_operations#String.Concat]]や加算演算子``+``による文字列の連結操作に相当します。
 

        

        
~
また、&msdn(netfx,member,System.Text.StringBuilder.AppendLine){StringBuilder.AppendLine};メソッドは、バッファの末尾に文字列を追加する点はAppendメソッドと同様ですが、自動的に改行文字も追加されます。 AppendLineメソッドに引数を指定しなかった場合は、改行文字のみが追加されます。
&msdn(netfx,member,System.Text.StringBuilder.AppendFormat){StringBuilder.AppendFormat};メソッドは、指定された書式に整形してからバッファに追加するメソッドです。 String.Formatメソッドによる書式化と文字列の連結を同時に行う操作に相当します。 String.FormatメソッドやConsole.WriteLineメソッドなどと同様に[[書式指定子>programming/netfx/string_formatting/0_formatstrings]]を指定することができます。
 

        

        
 
#tabpage(codelang=cs)
#tabpage(codelang=cs)
 
#code{{
#code{{
254,6 205,11
 
    sb.AppendLine();
    sb.AppendLine();
 

        

        
 
    Console.WriteLine("<{0}>", sb);
    Console.WriteLine("<{0}>", sb);
-

          
-
    // 書式を指定し、数値を文字列化して追加
-
    sb.AppendFormat("{0:D} {0:D4} {0:N4}", 72);
-

          
-
    Console.WriteLine("<{0}>", sb);
 
  }
  }
 
}
}
 
}}
}}
287,6 243,11
 
    sb.AppendLine()
    sb.AppendLine()
 

        

        
 
    Console.WriteLine("<{0}>", sb)
    Console.WriteLine("<{0}>", sb)
-

          
-
    ' 書式を指定し、数値を文字列化して追加
-
    sb.AppendFormat("{0:D} {0:D4} {0:N4}", 72)
-

          
-
    Console.WriteLine("<{0}>", sb)
 
  End Sub
  End Sub
 
End Class
End Class
 
}}
}}
302,14 263,14
 
<The quick brown fox jumps over the lazy dog
<The quick brown fox jumps over the lazy dog
 
The quick brown fox jumps
The quick brown fox jumps
 
>
>
-
<The quick brown fox jumps over the lazy dog
-
The quick brown fox jumps
-
72 0072 72.0000>
 
}}
}}
 

        

        
~
AppendLineメソッドでは改行文字に''常にEnvironment.NewLineが使われます''。 異なる改行文字を使用する方法については[[#append_specific_newline]]で後述します。
AppendFormatメソッドでは任意の引数を書式化して追加することが出来ますが、Appendメソッドでも文字列以外の値を追加することが出来ます。 この場合、引数として指定された値は既定の書式で自動的に文字列化されてから追加されます。
 

        

        
~
***StringBuilderと改行文字 [#append_specific_newline]
#tabpage(codelang=cs)
+
先に述べたとおり、AppendLineメソッドで追加される改行文字は''常にEnvironment.NewLineが使用されます''。 そのため、実行環境によって改行文字が変わると不都合がある困る場合や、CRまたはLFのみを追加したいといった場合は、AppendLineメソッドの代わりにAppendメソッドを使い、個別に改行文字を書き込む必要があります。
+

          
+
#tabpage(codelang=cs,container-title=改行文字を書き込む例)
 
#code{{
#code{{
 
using System;
using System;
 
using System.Text;
using System.Text;
318,19 279,28
 
{
{
 
  static void Main()
  static void Main()
 
  {
  {
~
    StringBuilder sb = new StringBuilder();
    StringBuilder sb = new StringBuilder(); // 空のStringBuilderを作成
 

        

        
~
    sb.Append("The quick brown fox jumps over the lazy dog");
    Console.WriteLine("<{0}>", sb);
+
    sb.AppendLine(); // 現在の環境での改行文字を追加
 

        

        
~
    sb.Append("The quick brown fox jumps over the lazy dog");
    // int型の数値を追加
~
    sb.Append("\r"); // CRを追加
    sb.Append(16);
-
    sb.AppendLine();
 

        

        
~
    sb.Append("The quick brown fox jumps over the lazy dog");
    Console.WriteLine("<{0}>", sb);
+
    sb.Append("\r"); // LFを追加
 

        

        
~
    sb.Append("The quick brown fox jumps over the lazy dog");
    // double型の数値を追加
~
    sb.Append("\r\n"); // CRLFを追加
    sb.Append(Math.PI);
-
    sb.AppendLine();
-

          
-
    Console.WriteLine("<{0}>", sb);
-

          
-
    // bool型の値を追加
-
    sb.Append(true);
-
    sb.Append(false);
-
    sb.AppendLine();
-

          
-
    Console.WriteLine("<{0}>", sb);
 
  }
  }
 
}
}
 
}}
}}
341,25 311,50
 

        

        
 
Class Sample
Class Sample
 
  Shared Sub Main()
  Shared Sub Main()
~
    Dim sb As New StringBuilder()
    Dim sb As New StringBuilder() ' 空のStringBuilderを作成
 

        

        
~
    sb.Append("The quick brown fox jumps over the lazy dog")
    Console.WriteLine("<{0}>", sb)
+
    sb.AppendLine() ' 現在の環境での改行文字を追加
 

        

        
~
    sb.Append("The quick brown fox jumps over the lazy dog")
    ' Integer型の数値を追加
~
    sb.Append(ControlChars.Cr) ' CRを追加
    sb.Append(16)
-
    sb.AppendLine()
 

        

        
~
    sb.Append("The quick brown fox jumps over the lazy dog")
    Console.WriteLine("<{0}>", sb)
+
    sb.Append(ControlChars.Lf) ' LFを追加
 

        

        
~
    sb.Append("The quick brown fox jumps over the lazy dog")
    ' Double型の数値を追加
~
    sb.Append(ControlChars.CrLf) ' CRLFを追加
    sb.Append(Math.PI)
-
    sb.AppendLine()
-

          
-
    Console.WriteLine("<{0}>", sb)
-

          
-
    ' Boolean型の値を追加
-
    sb.Append(true)
-
    sb.Append(false)
-
    sb.AppendLine()
-

          
-
    Console.WriteLine("<{0}>", sb)
 
  End Sub
  End Sub
 
End Class
End Class
 
}}
}}
 
#tabpage-end
#tabpage-end
 

        

        
~
これとは別に、[[StringWriterクラス>programming/netfx/string/5_stringreaderwriter]]を使うことによっても、StringBuilderで任意の改行文字を使うようにすることができます。 &msdn(netfx,member,System.IO.StringWriter.NewLine){StreamWriter.NewLineプロパティ};を変更すると、書き込まれる改行文字を変更することができます。 次の例では、結果が分かりやすいように改行文字を"↵\r\n"に変更しています。 もちろん、改行文字にCRまたはLFのみを指定することもできます。
#prompt(実行結果){{
-
<>
-
<16
-
>
-
<16
-
3.14159265358979
-
>
-
<16
-
3.14159265358979
-
TrueFalse
-
>
-
}}
-

          
-
***StringBuilderと改行文字
-
先に述べたとおり、AppendLineメソッドで追加される改行文字は''常にEnvironment.NewLineが使用されます''。 そのため、実行環境によって改行文字が変わると不都合がある困る場合や、CRまたはLFのみを追加したいといった場合は、AppendLineメソッドの代わりにAppendメソッドを使い、個別に改行文字を書き込む必要があります。
-

          
-
なお、[[StringWriterクラス>programming/netfx/string/5_stringreaderwriter]]を使うことにより、StringBuilderへの文字列の追加に際して任意の改行文字を使うようにすることができます。 &msdn(netfx,member,System.IO.StringWriter.NewLine){StreamWriter.NewLineプロパティ};を変更すると、書き込まれる改行文字を変更することができます。 次の例では、結果が分かりやすいように改行文字を"↵\r\n"に変更しています。 もちろん、改行文字にCRまたはLFのみを指定することもできます。
 

        

        
 
#tabpage(codelang=cs)
#tabpage(codelang=cs)
 
#code{{
#code{{
440,138 435,6
 
StringWriterクラスについて詳しくは[[programming/netfx/string/5_stringreaderwriter]]をご覧ください。
StringWriterクラスについて詳しくは[[programming/netfx/string/5_stringreaderwriter]]をご覧ください。
 
#remarks-end
#remarks-end
 

        

        
+
**書式を指定した文字列の追加 (AppendFormat)
+
&msdn(netfx,member,System.Text.StringBuilder.AppendFormat){StringBuilder.AppendFormat};メソッドは、指定された書式に整形してからバッファに追加するメソッドです。 [[String.Formatメソッド>programming/netfx/string/1_operations#String.Format]]による書式化と文字列の連結を同時に行う操作に相当します。
+

          
+
AppendFormatメソッドでは、String.FormatメソッドやConsole.WriteLineメソッドなどと同様に[[書式指定子>programming/netfx/string_formatting/0_formatstrings]]を指定することができます。
+

          
+
#tabpage(codelang=cs)
+
#code{{
+
using System;
+
using System.Text;
+

          
+
class Sample
+
{
+
  static void Main()
+
  {
+
    StringBuilder sb = new StringBuilder(); // 空のStringBuilderを作成
+

          
+
    // 書式を指定し、数値72を文字列化して追加
+
    sb.AppendFormat("{0:D} {0:D4} {0:N4}", 72);
+

          
+
    Console.WriteLine(sb);
+
  }
+
}
+
}}
+
#tabpage(codelang=vb)
+
#code{{
+
Imports System
+
Imports System.Text
+

          
+
Class Sample
+
  Shared Sub Main()
+
    Dim sb As New StringBuilder() ' 空のStringBuilderを作成
+

          
+
    ' 書式を指定し、数値72を文字列化して追加
+
    sb.AppendFormat("{0:D} {0:D4} {0:N4}", 72)
+

          
+
    Console.WriteLine(sb)
+
  End Sub
+
End Class
+
}}
+
#tabpage-end
+

          
+
#prompt(実行結果){{
+
72 0072 72.0000
+
}}
+

          
+
AppendFormatメソッドでは任意の型の引数を書式化して追加することが出来ますが、Appendメソッドも同様に文字列以外の値を追加することが出来ます。 この際、引数として指定された値は既定の書式で自動的に文字列化されてから追加されます。
+

          
+
#tabpage(codelang=cs)
+
#code{{
+
using System;
+
using System.Text;
+

          
+
class Sample
+
{
+
  static void Main()
+
  {
+
    StringBuilder sb = new StringBuilder(); // 空のStringBuilderを作成
+

          
+
    Console.WriteLine("<{0}>", sb);
+

          
+
    // int型の数値を追加
+
    sb.Append(16);
+
    sb.AppendLine();
+

          
+
    Console.WriteLine("<{0}>", sb);
+

          
+
    // double型の数値を追加
+
    sb.Append(Math.PI);
+
    sb.AppendLine();
+

          
+
    Console.WriteLine("<{0}>", sb);
+

          
+
    // bool型の値を追加
+
    sb.Append(true);
+
    sb.Append(false);
+
    sb.AppendLine();
+

          
+
    Console.WriteLine("<{0}>", sb);
+
  }
+
}
+
}}
+
#tabpage(codelang=vb)
+
#code{{
+
Imports System
+
Imports System.Text
+

          
+
Class Sample
+
  Shared Sub Main()
+
    Dim sb As New StringBuilder() ' 空のStringBuilderを作成
+

          
+
    Console.WriteLine("<{0}>", sb)
+

          
+
    ' Integer型の数値を追加
+
    sb.Append(16)
+
    sb.AppendLine()
+

          
+
    Console.WriteLine("<{0}>", sb)
+

          
+
    ' Double型の数値を追加
+
    sb.Append(Math.PI)
+
    sb.AppendLine()
+

          
+
    Console.WriteLine("<{0}>", sb)
+

          
+
    ' Boolean型の値を追加
+
    sb.Append(true)
+
    sb.Append(false)
+
    sb.AppendLine()
+

          
+
    Console.WriteLine("<{0}>", sb)
+
  End Sub
+
End Class
+
}}
+
#tabpage-end
+

          
+
#prompt(実行結果){{
+
<>
+
<16
+
>
+
<16
+
3.14159265358979
+
>
+
<16
+
3.14159265358979
+
TrueFalse
+
>
+
}}
+

          
+
#remarks
+
書式化について詳しくは[[programming/netfx/string_formatting]]を参照してください。
+
#remarks-end
+

          
 
**文字列の挿入・削除・置換 (Insert, Remove, Replace)
**文字列の挿入・削除・置換 (Insert, Remove, Replace)
 
Stringクラスと同様、文字列の挿入・削除・置換には&msdn(netfx,member,System.Text.StringBuilder.Insert){StringBuilder.Insert};、&msdn(netfx,member,System.Text.StringBuilder.Remove){StringBuilder.Remove};、&msdn(netfx,member,System.Text.StringBuilder.Replace){StringBuilder.Replace};の各メソッドが使えます。 引数と動作はStringクラスのものとほぼ同じですが、InsertメソッドはAppendメソッド同様に文字列以外も追加出来ます。 なお、String.Removeメソッドとは異なり、StringBuilder.Removeメソッドでは削除する文字数を省略することは出来ません。
Stringクラスと同様、文字列の挿入・削除・置換には&msdn(netfx,member,System.Text.StringBuilder.Insert){StringBuilder.Insert};、&msdn(netfx,member,System.Text.StringBuilder.Remove){StringBuilder.Remove};、&msdn(netfx,member,System.Text.StringBuilder.Replace){StringBuilder.Replace};の各メソッドが使えます。 引数と動作はStringクラスのものとほぼ同じですが、InsertメソッドはAppendメソッド同様に文字列以外も追加出来ます。 なお、String.Removeメソッドとは異なり、StringBuilder.Removeメソッドでは削除する文字数を省略することは出来ません。
 

        

        
686,8 549,8
 
<The fax jumps aver the 3 white dags>
<The fax jumps aver the 3 white dags>
 
}}
}}
 

        

        
~
**メソッドチェイン
***メソッドチェイン
~
Append, AppendFormat, AppendLine, Insert, Remove, Replaceの各メソッドは、戻り値として''インスタンス自身''を返します。 これにより、stringクラスと同様に''メソッドチェイン''を記述出来ます。
Append, AppendFormat, AppendLine, Insert, Remove, Replaceの各メソッドは、戻り値としてインスタンス自身を返します。 これにより、stringクラスと同様にメソッドチェインを記述出来ます。
 

        

        
 
#tabpage(codelang=cs)
#tabpage(codelang=cs)
 
#code{{
#code{{
742,11 605,11
 
StringBuilder: <The fax jumps aver the 3 white dags>
StringBuilder: <The fax jumps aver the 3 white dags>
 
}}
}}
 

        

        
~
*バッファの操作
**バッファの操作
 
インスタンスの内容が不変であるStringクラスとは異なり、内容が可変であるStringBuilderクラスでは内部にサイズが変更可能なバッファを備えています。 ここではStringBuilderのバッファの操作を行うプロパティ・メソッドについて見ていきます。
インスタンスの内容が不変であるStringクラスとは異なり、内容が可変であるStringBuilderクラスでは内部にサイズが変更可能なバッファを備えています。 ここではStringBuilderのバッファの操作を行うプロパティ・メソッドについて見ていきます。
 

        

        
~
**文字列の長さとバッファのクリア (Length, Clear)
***文字列の長さとバッファのクリア (Length, Clear)
~
StringBuilderに格納されている文字数は&msdn(netfx,member,System.Text.StringBuilder.Length){Lengthプロパティ};で取得できます。 String.Lengthプロパティとは異なり、Lengthプロパティを設定することで文字列の長さを変更することができます。 Lengthを現在の長さより小さくすると文字列が切り詰められ、大きくするとヌル文字(U+0000)で埋められます。 また、Lengthプロパティを0にすることにより、バッファの内容をクリアすることが出来ます。
StringBuilderに格納されている文字数は&msdn(netfx,member,System.Text.StringBuilder.Length){Lengthプロパティ};で取得できます。 String.Lengthプロパティとは異なり、Lengthプロパティを設定することで文字列の長さを変更することもできます。 Lengthを現在の長さより小さくすると文字列が切り詰められ、大きくするとヌル文字(U+0000)で埋められます。 また、Lengthプロパティを0にすることにより、バッファの内容をクリアすることが出来ます。
 

        

        
 
#tabpage(codelang=cs)
#tabpage(codelang=cs)
 
#code{{
#code{{
917,9 780,8
 
<The quick brown fox> (Length=19)
<The quick brown fox> (Length=19)
 
}}
}}
 

        

        
~
**バッファの容量 (Capacity, EnsureCapacity)
***バッファの容量 (Capacity, EnsureCapacity)
 
StringBuilderクラスでは、常に文字列の実際の長さ以上のバッファが確保されています。 &msdn(netfx,member,System.Text.StringBuilder.Capacity){Capacityプロパティ};はバッファのサイズ(容量)を取得するためのプロパティです。 このプロパティを設定することでバッファのサイズを変更することが出来ます。 ただし、現在の文字列の長さ未満にすることは出来ません。
StringBuilderクラスでは、常に文字列の実際の長さ以上のバッファが確保されています。 &msdn(netfx,member,System.Text.StringBuilder.Capacity){Capacityプロパティ};はバッファのサイズ(容量)を取得するためのプロパティです。 このプロパティを設定することでバッファのサイズを変更することが出来ます。 ただし、現在の文字列の長さ未満にすることは出来ません。
+

          
 
また、&msdn(netfx,member,System.Text.StringBuilder.EnsureCapacity){EnsureCapacityメソッド};でもバッファのサイズを変更することが出来ますが、このメソッドでは容量を減らすことは出来ず、現在の容量よりも多く確保したい場合に使用します。 EnsureCapacityメソッドでバッファを確保する場合、実際に確保される容量が指定した容量よりも大きくなる場合があります。
また、&msdn(netfx,member,System.Text.StringBuilder.EnsureCapacity){EnsureCapacityメソッド};でもバッファのサイズを変更することが出来ますが、このメソッドでは容量を減らすことは出来ず、現在の容量よりも多く確保したい場合に使用します。 EnsureCapacityメソッドでバッファを確保する場合、実際に確保される容量が指定した容量よりも大きくなる場合があります。
 

        

        
 
StringBuilderのコンストラクタでも容量の初期値を指定してインスタンスを生成することが出来ます(指定しない場合は初期値16でバッファが確保されます)。 StringBuilderに追加しようとする文字列の量をあらかじめ予測出来る場合は、あらかじめ適切な容量のバッファを確保しておくことでバッファ確保によるオーバーヘッドを減らすことが出来ます。
StringBuilderのコンストラクタでも容量の初期値を指定してインスタンスを生成することが出来ます(指定しない場合は初期値16でバッファが確保されます)。 StringBuilderに追加しようとする文字列の量をあらかじめ予測出来る場合は、あらかじめ適切な容量のバッファを確保しておくことでバッファ確保によるオーバーヘッドを減らすことが出来ます。
1026,7 888,7
 
(Length=87, Capacity=100) <The quick brown fox jumps over the lazy dog The quick brown fox jumps over the lazy dog>
(Length=87, Capacity=100) <The quick brown fox jumps over the lazy dog The quick brown fox jumps over the lazy dog>
 
}}
}}
 

        

        
~
**バッファの最大容量 (MaxCapacity)
***バッファの最大容量 (MaxCapacity)
 
StringBuilderが確保するバッファの最大容量を指定することも出来ます。 最大容量を指定するには、コンストラクタで指定する必要があります。 特に指定しない場合は初期値Int32.MaxValue(2,147,483,647)が最大容量に指定されます。 インスタンスの最大容量は&msdn(netfx,member,System.Text.StringBuilder.MaxCapacity){MaxCapacityプロパティ};で取得することが出来ます。
StringBuilderが確保するバッファの最大容量を指定することも出来ます。 最大容量を指定するには、コンストラクタで指定する必要があります。 特に指定しない場合は初期値Int32.MaxValue(2,147,483,647)が最大容量に指定されます。 インスタンスの最大容量は&msdn(netfx,member,System.Text.StringBuilder.MaxCapacity){MaxCapacityプロパティ};で取得することが出来ます。
 

        

        
 
文字列を追加しようとしたときやバッファのサイズを変更しようとしたときなど、確保しようとしているバッファの容量が最大容量を超える場合はArgumentOutOfRangeExceptionがスローされます。
文字列を追加しようとしたときやバッファのサイズを変更しようとしたときなど、確保しようとしているバッファの容量が最大容量を超える場合はArgumentOutOfRangeExceptionがスローされます。
1102,7 964,7
 
(Length=19, Capacity=19) <The quick brown fox>
(Length=19, Capacity=19) <The quick brown fox>
 
}}
}}
 

        

        
~
*StringBuilderのパフォーマンス [#performance]
*StringBuilderのパフォーマンス
 
StringクラスとStringBuilderクラスの最大の違いは、文字列操作の都度インスタンスが生成されるかどうかですが、これによりパフォーマンスにも違いが現れます。 StringクラスとStringBuilderクラスを用いて文字列の追加を行い、実行時間にどれくらいの差があるかを比較してみます。 次のコードでは、文字列の追加を10,000回行っています。 あらかじめStringBuilderの容量を指定している点にも注目してください。
StringクラスとStringBuilderクラスの最大の違いは、文字列操作の都度インスタンスが生成されるかどうかですが、これによりパフォーマンスにも違いが現れます。 StringクラスとStringBuilderクラスを用いて文字列の追加を行い、実行時間にどれくらいの差があるかを比較してみます。 次のコードでは、文字列の追加を10,000回行っています。 あらかじめStringBuilderの容量を指定している点にも注目してください。
 

        

        
 
#code(cs,検証用に使ったコード){{
#code(cs,検証用に使ったコード){{

programming/netfx/string/5_stringreaderwriter/index.wiki.txt

current previous
104,42 104,6
 
piyo
piyo
 
}}
}}
 

        

        
+
StringReaderを使うことにより、StreamReaderのメソッドを使ってファイルから読み込むのと同様に文字列を扱うことができます。 次の例では、既存の文字列を読み込み、一行毎に分割して表示しています。
+

          
+
#code(cs,StringReaderを使って文字列を行ごとに分割する例){{
+
using System;
+
using System.IO;
+
using System.Xml;
+

          
+
class Sample
+
{
+
  static void Main()
+
  {
+
    // 複数の"行"が含まれる文字列
+
    string text = "foo\r\nbar\r\nhoge\r\npiyo";
+

          
+
    using (StringReader r = new StringReader(text))
+
    {
+
      for (;;)
+
      {
+
        // StringReaderを使って文字列textから"一行"ずつ読み込む
+
        string line = r.ReadLine();
+

          
+
        if (line == null) break;
+

          
+
        Console.WriteLine(line);
+
      }
+
    }
+
  }
+
}
+
}}
+

          
+
#prompt(実行結果){{
+
foo
+
bar
+
hoge
+
piyo
+
}}
 

        

        
 

        

        
 
*StringWriterクラス
*StringWriterクラス

programming/netfx/string/6_securestring/index.wiki.txt

current previous
317,15 317,8
 

        

        
 
}}
}}
 

        

        
~
#remarks
SecureStringに格納したパスワードが暗号化された状態なのはリクエストが送信されるまでである点に注意してください。 リクエストがサーバに送信される時点でSecureStringから暗号化が解除されたパスワードが取り出されます。
+
上記の例において、SecureStringに格納したパスワードが暗号化された状態であるのはリクエストが送信されるまでである点に注意してください。 リクエストがサーバに送信される時点で、SecureStringから暗号化が解除されたパスワードが取り出されます。 Digest認証では取り出されたパスワードがハッシュ化された上で送信されますが、Basic認証ではパスワードが平文で送信されます。
 

        

        
+
SecureStringはあくまでメモリ上の文字列を暗号化しておくためのものであり、通信経路上での文字列の暗号化には寄与しません。 したがって、上記の例のようにSecureStringが保持している文字列を通信経路を介して送受信する場合は、HTTPではなくHTTPSを使う、SslStreamクラスと組み合わせてSSL/TLSを使うなどにより通信経路の暗号化もあわせて行うようにする必要があります。
+
#remarks-end
+

          
+
#remarks
+
この例では、&msdn(netfx,member,System.Console.ReadKey){Console.ReadKeyメソッド};を使うことにより、入力されたパスワードがコンソール上に表示されない(エコーバックしない)ようにしています。 実装の詳細、より適切な実装方法については[[programming/netfx/tips/console_input_without_echo_back]]を参照してください。
+
#remarks-end
 

        

        
 

        

        
 
*Stringへの変換
*Stringへの変換