Adding more operators with Where as an example ( Query Design continued ):

This post is a part of a series of posts about query design. For the previous post see: https://blogs.msdn.com/vladimirsadov/archive/2007/06/07/query-pattern-composability-query-design-continued.aspx

As you might have seen queries have a lot more operators than just Select. Here we will take a look how we can add support for Where to our queryable type.

 

It is surprisingly easy to implement Where. Compiler will use any function that is named Where, can be applied to the source collection and takes a delegate function that takes an element of the collection and returns a Boolean result.

 

I will not do delayed execution tricks in this sample for simplicity (do not want to implement all that IEnumerable support again), however it is fairly trivial to generalize this sample so that both Select and Where are delay-executed.

 

Class MyGenericQueryable(Of T)

    Public elements As IEnumerable(Of T)

    Public Function [Select](Of S)(ByVal projection As Func(Of T, S)) As MyGenericQueryable(Of S)

        Dim new_col As New MyGenericQueryable(Of S)

        Dim new_elements As New List(Of S)

        new_col.elements = new_elements

        For Each element In elements

            new_elements.Add(projection(element))

        Next

        Return new_col

    End Function

    Public Function Where(ByVal predicate As Func(Of T, Boolean)) As MyGenericQueryable(Of T)

        Dim new_col As New MyGenericQueryable(Of T)

        Dim new_elements As New List(Of T)

        new_col.elements = new_elements

        For Each element In elements

            If predicate(element) Then

                new_elements.Add(element)

            End If

        Next

        Return new_col

    End Function

End Class

Module Module1

    Sub Main()

        Dim arr As Integer() = New Integer() {1, 2, 3}

        Dim col As New MyGenericQueryable(Of Integer)

        col.elements = arr

        Dim q = From i In col Where i > 1 Select i

        For Each t In q.elements

            Console.WriteLine(t)

        Next

    End Sub

End Module