VB で LINQ で連番

Enumerable.Range 使うと簡単にできるみたい。

Module Module1
    Sub Main()
        Dim numbers = From n In Enumerable.Range(1, 100) Select n * n
        ' メソッド構文
        ' Dim numbers = Enumerable.Range(1, 100).Select(Function(n) n * n)
        For Each number In numbers
            Console.WriteLine(number)
        Next
        Console.ReadLine()
    End Sub
End Module

結果

1
4
9
・・・(中略)・・・
9604
9801
10000

#TL で突っ込み頂いたので書き直しました(汗


  

そもそもの発端

下記のコードを LINQ で書き換えられないか考えていたところ、たまたま TL に LINQ の話が流れてたのでチャレンジしたいと思いました。

command.Parameters.AddWithValue("pattern1", checkCollection(0).Id)
command.Parameters.AddWithValue("pattern2", checkCollection(1).Id)
command.Parameters.AddWithValue("pattern3", checkCollection(2).Id)
command.Parameters.AddWithValue("pattern4", checkCollection(3).Id)
command.Parameters.AddWithValue("pattern5", checkCollection(4).Id)


コレクション「checkCollection」のアイテムが5個に満たないケースが発生したため、修正が発生しました。

For i = 0 To 4
    command.Parameters.AddWithValue(String.Format("pattern{0}", i + 1), -1)
Next
Dim j = 0
For Each ch In checkCollection
    command.Parameters(j).Value = ch.Id
    j += 1
Next


For 〜For Each 文が連続して書いてあるのを見ると、どうにも LINQ に置き換えたくなります。LINQ 星人じゃないので、LINQ で連番どうやって実装するか少し頭を使いましたが、Enumerable.Range を使えばいいと知り、まず上の For 文だけでも LINQ に変更してみます。

Dim c = From n In Enumerable.Range(1, 5) Select New MySqlParameter(String.Format("pattern{0}", n), -1)
command.Parameters.AddRange(c.ToArray())
Dim i = 0
For Each ch In checkCollection
    command.Parameters(i).Value = ch.Id
    i += 1
Next


ただしまだ美しくないですね。下に残ってる For Each も一つのクエリで纏めたいです。
クエリ構文じゃ限界ぽいので、メソッド構文で対応してみました。

Dim c = Enumerable.Range(1, 5).Select(
    Function(number) As MySqlParameter
        Dim ret = New MySqlParameter(String.Format("pattern{0}", number), -1)
        If (number < checkCollection.Count) Then
            ret.Value = number
        End If
        Return ret
    End Function)
command.Parameters.AddRange(c.ToArray())


C# の構文に比べるとかなり冗長感ありますが、まあこれで解決ということで。