So I’ve been making a conscious effort to try to use generic lists because they save time. I’m so used to building all of my objects and collections as custom objects and custom collections that some habits are hard to break. However, part of what is driving me to really want to use the generic lists is what I read in Ken Getz’s recent MSDN article about Predicates and Actions. I read his article and was thinking “Great – another example of the framework doing my work for me!”
Unfortuantely my first try didn’t meet with very much success. I’ve got a custom PurchaseOrder object with tons of properties and behaviors associated. I wanted to find a specific PO in my generic list based on the PurchaseOrderNumber. So I try code that looks like this:
Dim _purchaseOrders As List(Of PurchaseOrder)
_purchaseOrders.Find(AddressOf FindPOByID)
Because I needed to pass in the PO ID value dynamically, my FindPOByID function would have looked something like this:
Public Function FindPOByID(ByVal aPO As PurchaseOrder, ByVal POID As Integer) As Boolean
If aPO.PurchaseOrderNumber = POID Then
Return True
Else
Return False
End If
End Function
Of course, that doesn’t match the signature of the System.Predicate delegate

So I ended up with a for each loop:
Dim isEDI As Boolean
For Each PO As PurchaseOrder In _purchaseOrders
If PO.PurchaseOrderNumber = purchaseOrderNumber Then
isEDI = PO.EDI
End If
Next
Slightly disappointing for my first attempt, but my next attempt at System.Action worked swimmingly. I have a custom collection of ReceiveItems. Each ReceiveItem has a Receive method which does the required database work to import the item into inventory. My collection (a List of ReceiveItems) also implements a Receive function – receive the entire group. This is accomplished on the collection level with minimal code:
Public Function Receive() As Boolean
Try
_receiveItems.ForEach(AddressOf ItemReceive)
Return True
Catch ex As Exception
Debug.Print("Error receiving items: " & ex.Message) ‘Not fully implemented yet
Return False
End Try
End Function
Private Shared Sub ItemReceive(ByVal aReceiveItem As ReceiveItem)
aReceiveItem.Receive()
End Sub
Notice the simple List.ForEach code. In terms of maintainability, this solution can’t be beat!
Finally, I tried the Predicate again:
Public Function ValidateItems() As Boolean
Dim invaliditem As ReceiveItem = _receiveItems.Find(AddressOf NotMyComputer)
If invaliditem Is Nothing Then
Return True
Else
Return False
End If
End Function
This works great given the custom business requirement of matching a receive item to the PC it was received on.
In general my conclusion is that the Predicates and Actions are fantastic methods of reducing the complexity of code, but they feel slightly limited due to the strict adherance to a single delegate function signature. The only problem I can really point out in Ken’s article is that his examples are somewhat contrived, which gave me initially a hard time understanding just how to use this in my own work.