2017の新機能を使う方法を追加しました。【2017/02/22】初版公開。15)の値タプルを利用する記述を追加したものです。コレクションを処理するforeachループの中で繰り返し回数が必要になることがある。ループ外でカウンター変数を定義しておいてループ内でインクリメントすれば実現できるとはいえ、もっとスマートに書けないものだろうか?foreachループで現在の繰り返し回数を使うには?LINQのSelect拡張メソッド(System.Linq名前空間のEnumerableクラス)を使うとスマートに書ける。次のコードのようにSelect拡張メソッドを使って、コレクションの要素とインデックスを持つ匿名型のオブジェクトをループするごとに作ればよいのだ。......valueとindexを使った処理を書く......NextSelect拡張メソッドでループのインデックスを得る(上:C#、下:VB)Select拡張メソッドに与えるラムダ式には、このように2つの入力パラメーターを持つものもある。最初の入力パラメーター(この例では「Value」)はコレクションの各要素であり、2つ目の入力パラメーター(この例では「Index」)はコレクションのインデックス(ゼロ始まり)である。この2つの入力パラメーターを、そのまま匿名型のオブジェクトに格納してやり、それをループ変数(この例では「item」)としている。ループ内では、ループ変数のプロパティとして、コレクションの要素とインデックスを得られる。ここでは説明のためにループ内で一時変数(「value」と「index」)にコレクションの要素とインデックスを代入している。簡単な処理ならば、一時変数に代入せずそのまま(「item.Value」や「item.Index」を)使えばよい。実際の例コンソールアプリの例を示そう(次のコード)。2015またはそれ以降)。List<string>{"後漢の建寧元年のころ。","一人の旅人があった。","年の頃は二十四、五。0:後漢の建寧元年のころ。1:一人の旅人があった。2:年の頃は二十四、五。{"後漢の建寧元年のころ。","一人の旅人があった。","年の頃は二十四、五。0:後漢の建寧元年のころ。1:一人の旅人があった。2:年の頃は二十四、五。2015からのものだ。6.0]」をご覧いただきたい。TIPS:VB.NETでクラス名を省略してメソッドや定数を利用するには?」で解説している。14で追加された補間文字列機能を使用する」)を見てほしい。Studioでコンソール・アプリケーションのデバッグ実行時にコマンド・プロンプトを閉じないようにするには?」をご覧いただきたい。参考までに、従来の書き方も示しておこう(次のコード)。Select拡張メソッドを使ったコードより、2行多くなり、「カウンター変数を間違いなくカウントアップする」ことに注意する必要もある。i7で回して1ミリ秒違うかどうかという程度である)。1WriteLine($"{index}:{value}")Next従来の書き方の例(上:C#、下:VB)カウンター変数を間違いなくカウントアップするために、ループの冒頭でインクリメントしている。ループ末尾でインクリメントしていると、(特にループ内の処理が長いと)うっかり途中でcontinue文を使ってしまって正しくカウントされなくなるというバグを作り込んでしまう可能性があるからだ。先のSelect拡張メソッドを使うコードでは、そんな心配はしなくてよいのだ。tuples)を使うと、特にC#ではとてもスマートに記述できる(VBでは従来とそれほど変わらない)。4.7のプレビュー版が利用可能になり、それを選択することでパッケージを追加することなく値タプルが利用できた)。値タプルを使うと、次のコードのように書ける。NuGetから「System.ValueTuple」パッケージをプロジェクトにインストールしておく必要がある。types」を参照してもらいたい(本稿執筆時点では英文のみ)。VBの解説は、本稿執筆時点ではまだないようだった。Select拡張メソッドに与えているラムダ式の意味は、「コレクションの要素vとインデックスiを受け取り、vとiを持つタプルにして返す」というものだ。i)」はタプルの生成である。VBのコードは、タプルを生成するときにそれぞれの値に名前を付けている(C#のコードは、生成したタプルの持つ値は匿名)。タプルを受け取るとき、C#はその場で分解できる(タプルそのものを変数に受け取ることも可能)。index)」は、受け取ったタプルを分解して2つの変数「value」と「index」に代入している。VBでは、タプルの受け取りと分解をいっぺんに記述できず、タプルのままいったん変数に代入しなければならないようだ。上のコードのSelect拡張メソッドの中身は、何をやっているのかとっさには分からないだろう。拡張メソッドに切り出して名前を付けておくと、分かりやすくなる(次のコード)。collection.ToTuples()WriteLine($"{t.Index}:{t.Value}")Next値タプルに変換する拡張メソッドを使う例(上:C#、下:VB)C#のforeach文の記述は、理想に近づいたのではないだろうか。foreach文のループ変数としてvalueとindexの2つがあるかのように書けている。いえ実際には、本稿冒頭で示したコードの匿名型がタプルに変わっただけであり、ループごとにオブジェクト(匿名型または値タプル)を生成することには変わりがない。まとめSelect拡張メソッドを使うと、foreachループの中で現在の繰り返し回数をスマートに得られる。カウンター変数の管理をしなくて済むというメリットがある。実行速度は従来の書き方よりも少し遅くなる。15では値タプルを利用することで、より簡潔な記述が可能になる。15の新機能を使う方法を追加しました。【2017/02/22】初版公開。メールマガジンをご購読ください。申し込みページへITmediaはアイティメディア株式会社の登録商標です。