Better than Contains()

Sometimes you wish you could do better than the method you need to use. Case in point: Contains(). It is a fine method and is meant for more than strings. If you need custom logic to decide if two objects are equal or “the same” for the sake of sorting or searching you write your own comparer and pass that in. So, I don’t have anything against the Contains() method for any reason, I only find it a bit too generic when all I have is a list of strings and want to see if I have a match that doesn’t care about case.

I figured LINQ might be a good fit. So I whipped up a simple* LINQ expression. I was able to do a select using a String.Compare() call, then I could pass in the ignoreCase parameter to get my desired results.

     Private Sub CheckIfAllowed(ByVal myTargetPath As String)
        Dim allowedPageList As New List(Of String)
        allowedPageList.Add("Logoff.aspx")
        allowedPageList.Add("AccessDenied.aspx")
        allowedPageList.Add("Login.aspx")

        Dim found = From p In allowedPageList Where String.Compare(myTargetPath, p, ignoreCase:=True) = 0
        If found.Count > 0 Then
            MessageBox.Show("Found")
        Else
            MessageBox.Show("Not Found")
        End If
    End Sub

So, that was pretty cool. The next logical step seemed to be to create an extension for the List(Of String) class.

     ''' <summary>
        ''' Searches the List(Of String) using case-insensitive LINQ query
        ''' </summary>
        ''' <param name="list"></param>
        ''' <param name="value">the string to search for</param>
        ''' <returns>true if item is found. default: false</returns>
        ''' <remarks></remarks>
        <Extension()> _
        Public Function ContainsIgnoreCase(ByVal list As List(Of String), ByVal value As String) As Boolean
            Dim found = From p In list Where String.Compare(value, p, ignoreCase:=True) = 0
            Return found.count > 0
        End Function

So I can have this “new function” available on all List(Of String) instances.

  If allowedPageList.ContainsIgnoreCase(myTargetPath) Then
         MessageBox.Show("Found")
  Else
         MessageBox.Show("Not Found")
  End If

After I created my extension I thought: “I probably just duplicated something that was already part of a special collection type” so I looked thru the collection types and, under the Specialized namespace I found the class StringCollection. This exposes a Contains() method as well. However, even though it is a string specific collection the documentation indicates:

“This method determines equality by calling Object.Equals. String comparisons are case-sensitive.”

*I still can’t write one without Googling for samples. Learning more about the syntax is always on my to do list.

Posted on ASP.NET Weblogs        © Copyright 2009 - Andreas Zenker

3 Comments

  • Three suggestions:

    1. You should be using String.Equals(x, y, StringComparison) instead of String.Compare;

    2. You should use Any() instead of Count() > 0;

    3. Your extension method doesn't need a List(Of String), only an IEnumerable(Of String), which would make it more useful:

    _
    Public Function ContainsIgnoreCase(ByVal list As IEnumerable(Of String), ByVal value As String) As Boolean
    Return (From p In list Where String.Equals(value, p, StringComparison.OrdinalIgnoreCase)).Any()
    End Function

  • Great comment! Thanks for the good reminders/tweaks. I will update the post to reflect the changes.

  • Any chance of a c# conversion of that function? Soz, i tried. Thanks

Comments have been disabled for this content.