Fluent iComparable for Everyone

I was working on my Fluent Helper class and I wanted to add a BirthDate field to my example person class. I wanted to be able to filter item if they were Greater or Less than a date. I then realized that I also wanted that for my String class. The String and Date types both support the iComparable interface. Most types do. If I made a generic class using icomparable then I could use that for Date and use it as a base class for Strings. Here is the new class FluentComparableList that can be a base for most other types:

Public Class FluentComparableList(Of ListType As {IList, New}, ItemType, ParamaterType As IComparable)
    Public InternalList As ListType
    Public InternalFunction As Func(Of ItemType, ParamaterType)

    Sub New(ByRef list As ListType, ByVal _Func As Func(Of ItemType, ParamaterType))
        InternalList = list
        InternalFunction = _Func
    End Sub

    Public Function GetNewList(ByRef _Func As Func(Of ItemType, Boolean))
        GetNewList = New ListType
        For Each item In InternalList
             If _Func(item) Then GetNewList.Add(item)
        Next
    End Function

    Public Function Greater(ByVal i As Integer) As ListType
        Return GetNewList(Function(item) InternalFunction(item).CompareTo(i) > 0)
    End Function

    Public Function Lesser(ByVal i As Integer) As ListType
        Return GetNewList(Function(item) InternalFunction(item).CompareTo(i) < 0)
    End Function
etc...

When I refactored the StringWhere class I renamed it FluentStringList and ended up with:

Public Class FluentStringList(Of ListType As {IList, New}, ItemType)
    Inherits FluentComparableList(Of ListType, ItemType, String)

    Sub New(ByRef list As ListType, ByVal _Func As Func(Of ItemType, String))
        MyBase.New(list, _Func, _Not)
        InternalList = list
        InternalFunction = _Func
    End Sub

    Public Function StartsWith(ByVal value As String) As ListType
        Return GetNewList(Function(item) InternalFunction(item).StartsWith(value))
    End Function

    Public Function EndsWith(ByVal value As String) As ListType
        Return GetNewList(Function(item) InternalFunction(item).EndsWith(value))
    End Function

    Public Function Contains(ByVal value As String) As ListType
        Return GetNewList(Function(item) InternalFunction(item).Contains(value))
    End Function

    Public Function IndexOf(ByVal value As String) As FluentComparableList(Of ListType, ItemType, Integer)
        Return New FluentComparableList(Of ListType, ItemType, Integer)(InternalList, Function(s) InternalFunction(s).IndexOf(value))
    End Function

End Class

You also see a new function on the FluentStringList class called IndexOf. Yes, that is the collection version of the string function IndexOF which tells you the placement of one text string in another. Since it uses the FluentComparableList I can use the integer from the IndexOf and check if it is greater than or less than another integer. For example, Let’s say i want to count all the people with names where the letter ‘e’ was in the name but it was further than the 2nd character from the beginning. It would be as simple as:

People.Name.IndexOf("e").Greater(2).count

Now that was fun! I almost forgot about the BirthDate Field. Here is the Person and the People classes with it implemented:

Public Class Person
    Public Name As String
    Public BirthDate As Date

    Sub New(ByVal _Name As String, ByVal _BirtDate As Date)
        Name = _Name
        BirthDate = _BirtDate
    End Sub

End Class


Public Class PersonList
    Inherits List(Of Person)

    Sub New()
        MyBase.new()
    End Sub

    Sub New(ByVal List As List(Of Person))
        MyBase.New(List)
    End Sub

    Public Function Name() As FluentStringList(Of PersonList, Person)
        Return New FluentStringList(Of PersonList, Person)(Me, Function(s) s.Name)
    End Function

    Public Function BirthDate() As FluentComparableList(Of PersonList, Person, Date)
        Return New FluentComparableList(Of PersonList, Person, Date)(Me, Function(s) s.BirthDate)
    End Function

End Class

Now to see how many people were borne since 1973 I can:

People = New PersonList
People.Add(New Person("Bentley", "1/1/1973"))
People.Add(New Person("Joe", "2/1/1992"))
People.Add(New Person("Jimmy", "3/1/2005"))
People.Add(New Person("Karla", "4/1/1984"))
People.Add(New Person("Cameron", "5/1/1950"))

Debug.Print People.BirthDate.Greater("12/31/1972")
'Prints 4 (only Cameron was borne before 12/31/1972)

I would like to hear what you think in the comments below. Please don’t frustrate, educate!