Aug 01 2007

Using Predicate Generic Delegates in VB.Net with .NetTiers

Category: .NetTiers, Programminglomaxx @ 11:23 pm

This post is absolutely essential if you use the Find method on generics lists in VB.Net with .NetTiers. Here’s some background. I was recently doing some work on an application that required me to loop through a TList that contained nearly 37000 objects and see if they existed in another TList that also contained around 37000 objects. So to achieve this I whipped up some code that looked a little like this:

For Each item As BaseAddress In lstProdContacts

Dim tmpContact As BaseAddress = lstTempContacts.Find(BaseAddressColumn.IdBaseAddress, item.IdBaseAddress)

'Use tmpContact here

Next

It worked, but the thing I found was that it was horribly slow. To execute on my list of 37000 contact it took well over 8 minutes which was simply unacceptable.

This post from the .NetTiers team pretty much confirmed what I had suspected and that this Find method was in fact using reflection. From my previous experience as a DNN programmer, I knew that reflection was expensive and should be used sparingly.

The post however, offered me an alternative solution: Anonymous Methods. However, this also presented another problem, VB.Net does not support anonymous methods. I was able to hack up some code that would use a wrapper class but it was all starting to get a little messy until I came across a brilliant post by Paul Stovell on Almost Anonymous methods in VB.net.

It wasn’t exactly what I wanted because I still had to define a function that would match the contacts, but it was a still a far cleaner solution. I put Pauls class in my Utility namespace and now when I want to use an (almost) anonymous method I do something like this:

For Each prodContact As BaseRfaAddress In lstProdContact

Dim tempContact As BaseRfaAddress = lstProdContact.Find(New PredicateWrapper(Of BaseRfaAddresse, BaseRfaAddresse)(prodContact, AddressOf ContactMatch))

'Use tmpContact here

Next

Then in the same class I define a function that will determine if a contact is a match or not and we’re done.

Public Shared Function ContactMatch(ByVal item As BaseRfaAddress, ByVal argument As BaseRfaAddress) As Boolean

Return item.IdBaseRfaAddress.Equals(argument.IdBaseRfaAddress)

End Function

It isn’t by any means as clean as anonymous methods in c# but now when I run the loop it runs in well under a minute which is an almost unbelievable performance gain and well worth the effort of implementation.