Aug 01 2007
Using Predicate Generic Delegates in VB.Net with .NetTiers
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.
