2013-02-04T14:58:49の更新内容

programming/netfx/enumeration/index.wiki.txt

current previous
1144,7 1144,7
 

        

        
 
これを回避するには、foreachによる列挙中はコレクションを変更しないようにするしかありません。 逆に言えば、''foreachでの列挙中''に''列挙中のコレクションを変更''しなければよいため、次のような代替手段を使うことができます。
これを回避するには、foreachによる列挙中はコレクションを変更しないようにするしかありません。 逆に言えば、''foreachでの列挙中''に''列挙中のコレクションを変更''しなければよいため、次のような代替手段を使うことができます。
 

        

        
~
**代替方法1 for文を使う
**for文を使う
 
一つの代替方法に、for文などを使いインデックスを指定してコレクションを列挙・変更する方法があります。 この方法では、コレクションを変更することにより列挙中の要素のインデックスが変わる場合がある点に注意が必要です。 先の例を、for文/Do Whileステートメントを使って書き換えると次のようになります。
一つの代替方法に、for文などを使いインデックスを指定してコレクションを列挙・変更する方法があります。 この方法では、コレクションを変更することにより列挙中の要素のインデックスが変わる場合がある点に注意が必要です。 先の例を、for文/Do Whileステートメントを使って書き換えると次のようになります。
 

        

        
 
#tabpage(C#)
#tabpage(C#)
1203,7 1203,7
 
2, 4, 6, 
2, 4, 6, 
 
}}
}}
 

        

        
~
**代替方法2 別のコレクションに結果を格納する
**別のコレクションに結果を格納する
 
もう一つは、元のコレクションには変更を加えず、別のコレクションを用意してそこに結果を格納する方法です。 この方法の場合、元のコレクションには変更を加えないため、foreach文/For Eachステートメントでの列挙中でも例外はスローされません。 先の例ではリストから奇数の要素を削除するようにしていましたが、次のコードでは奇数以外の要素(つまり偶数)を別のリストに格納することで同等の結果を得られるようにしています。
もう一つは、元のコレクションには変更を加えず、別のコレクションを用意してそこに結果を格納する方法です。 この方法の場合、元のコレクションには変更を加えないため、foreach文/For Eachステートメントでの列挙中でも例外はスローされません。 先の例ではリストから奇数の要素を削除するようにしていましたが、次のコードでは奇数以外の要素(つまり偶数)を別のリストに格納することで同等の結果を得られるようにしています。
 

        

        
 
#tabpage(C#)
#tabpage(C#)
1262,12 1262,8
 
2, 4, 6, 
2, 4, 6, 
 
}}
}}
 

        

        
~
**List.ForEachメソッドとコレクションの変更 [#List.ForEach]
**ForEachメソッドを使う
~
列挙するコレクションが&msdn(netfx,type,System.Collections.Generic.List`1){Listクラス};の場合は、&msdn(netfx,member,System.Collections.Generic.List`1.ForEach){ForEachメソッド};を使って列挙する事が出来ます。 このメソッドでの列挙中に変更を加える操作はサポートされないため、列挙中のInvalidOperationExceptionを回避する目的でList.ForEachメソッドを使用することはできません。
列挙するコレクションが&msdn(netfx,type,System.Collections.Generic.List`1){Listクラス};の場合は、&msdn(netfx,member,System.Collections.Generic.List`1.ForEach){ForEachメソッド};を使って列挙する事が出来ます。 このメソッドで列挙する場合は、列挙中にListの内容を変更しても例外がスローされることはありません。
+

          
+
.NET Framework 4.0以前の場合は、ForEachメソッドでの列挙中に変更を加えてもInvalidOperationExceptionはスローされませんが、結果は未定義となります。 .NET Framework 4.5以降の場合は、列挙中に変更を加えるとforeach文の場合と同様にInvalidOperationExceptionがスローされます。
+

          
+
次の例では、ForEachメソッドでの列挙中に要素の削除を行っていますが、結果は意図した通りにはなりません。
 

        

        
 
#tabpage(C#)
#tabpage(C#)
 
#code(cs){{
#code(cs){{
1277,7 1273,7
 
class Sample {
class Sample {
 
  static void Main()
  static void Main()
 
  {
  {
~
    List<int> list = new List<int>(new int[] {2, 4, 5, 6, 1, 3, 7});
    List<int> list = new List<int>(new int[] {1, 2, 3, 4, 5, 6, 7});
 

        

        
 
    // Listから奇数の要素を削除したい
    // Listから奇数の要素を削除したい
 
    list.ForEach(delegate(int val) {
    list.ForEach(delegate(int val) {
1300,7 1296,7
 

        

        
 
Class Sample
Class Sample
 
  Shared Sub Main()
  Shared Sub Main()
~
    Dim list As New List(Of Integer)(New Integer() {2, 4, 5, 6, 1, 3, 7})
    Dim list As New List(Of Integer)(New Integer() {1, 2, 3, 4, 5, 6, 7})
 

        

        
 
    ' Listから奇数の要素を削除したい
    ' Listから奇数の要素を削除したい
 
    list.ForEach(Sub(val)
    list.ForEach(Sub(val)
1317,11 1313,11
 
}}
}}
 
#tabpage-end
#tabpage-end
 

        

        
~
#prompt(.NET Framework 4.0以前での実行結果){{
#prompt(実行結果){{
~
2, 4, 6, 3,
2, 4, 6, 
 
}}
}}
 

        

        
~
なお、ForEachメソッドの使い方については[[programming/netfx/collections/2_generic_1_list]]で解説しています。
ForEachメソッドの使い方については[[programming/netfx/collections/2_generic_1_list]]で解説しています。
 

        

        
 
*IEnumerable・IEnumeratorを実装しない型の列挙
*IEnumerable・IEnumeratorを実装しない型の列挙
 
ここまでの解説では、列挙を行うためにはIEnumerableを実装する必要があるとしてきました。 しかし実際には、C#のforeach文、VBのFor EachステートメントではIEnumerableを実装していない型でも列挙操作を行うことが出来ます。 以下は、IEnumerable・IEnumeratorを実装していないクラスで列挙操作を行う例です。
ここまでの解説では、列挙を行うためにはIEnumerableを実装する必要があるとしてきました。 しかし実際には、C#のforeach文、VBのFor EachステートメントではIEnumerableを実装していない型でも列挙操作を行うことが出来ます。 以下は、IEnumerable・IEnumeratorを実装していないクラスで列挙操作を行う例です。

programming/netfx/collections/2_generic_1_list/index.wiki.txt

current previous
918,7 918,7
 
}}
}}
 

        

        
 
**列挙操作 [#List_Enumeartion]
**列挙操作 [#List_Enumeartion]
~
Listクラスでは、foreach文による列挙の他に、&msdn(netfx,member,System.Collections.Generic.List`1.ForEach){ForEachメソッド};による列挙が出来るようになっています。 このメソッドは、引数に列挙時に個々の要素に対して行う操作をデリゲートとして指定します。
Listクラスでは、foreach文による列挙の他に、&msdn(netfx,member,System.Collections.Generic.List`1.ForEach){ForEachメソッド};による列挙が出来るようになっています。 このメソッドは、引数に列挙時に個々の要素に対して行う操作を指定します。
 

        

        
 
#tabpage(C# 2.0)
#tabpage(C# 2.0)
 
#code(cs){{
#code(cs){{
1015,7 1015,7
 
Eve
Eve
 
}}
}}
 

        

        
~
foreach文で列挙している途中にRemoveメソッドやAddメソッドを呼び出してListクラスの内容を変更することは無効な操作であるため、InvalidOperationExceptionがスローされます。 ForEachメソッドを使った列挙の場合でも同様に無効な操作となりますが、.NET Framework 4.0以前ではInvalidOperationExceptionがスローされず、.NET Framework 4.5以降ではスローされるようになっています。 この点については[[programming/netfx/enumeration#List.ForEach]]で詳しく解説しています。
foreach文で列挙している途中にRemoveメソッドやAddメソッドを呼び出してListクラスの内容を変更することは無効な操作であるため、InvalidOperationExceptionがスローされます。 一方、ForEachメソッドを使った列挙の場合は、列挙中にListクラスに変更を加えても例外がスローされることはありません。 この点については[[programming/netfx/enumeration]]で詳しく解説しています。
 

        

        
 
**型変換 [#List_Conversion]
**型変換 [#List_Conversion]
 
&msdn(netfx,member,System.Collections.Generic.List`1.ConvertAll){ConvertAllメソッド};を使うと、要素のすべてを別の型に変換出来ます。
&msdn(netfx,member,System.Collections.Generic.List`1.ConvertAll){ConvertAllメソッド};を使うと、要素のすべてを別の型に変換出来ます。