Passing parameters to delegates in VB.NET
In C# we have anonymous methods. You can read about them and how they are implemented in this post on Raymond Chens blog:
http://blogs.msdn.com/oldnewthing/archive/2006/08/02/686456.aspx
One of the features of anonymous methods is they allow you to use variables that would normally be out of scope. Raymond explains that this works by generating a class under the hood, populating it with the variables and then passing the method. Here is an example of what C# can do:
public void Main()
{
var developers = new List<string>(new [] { "Woody Allen", "Bill Gates" } );
var greatDeveloperFirstName = "Bill";
var greatDevelopers = developers.FindAll(
delegate (string developerName) {
// Note that I am using a variable that would be "out of scope" if
// this wasn't an anonymous method:
return developerName.StartsWith(greatDeveloperFirstName);
});
}
In VB.NET, since you can't do anonymous methods, it also makes it hard to pass arguments to methods that expect a Predicate<T>
(such as List<T>.FindAll()
).
Here's a VB.NET class that you can reuse to "wrap" a Predicate<T>
in order to pass arguments to it.
Public Delegate Function PredicateWrapperDelegate(Of T, A) _
(ByVal item As T, ByVal argument As A) As Boolean
Public Class PredicateWrapper(Of T, A)
Private _argument As A
Private _wrapperDelegate As PredicateWrapperDelegate(Of T, A)
Public Sub New(ByVal argument As A, _
ByVal wrapperDelegate As PredicateWrapperDelegate(Of T, A))
_argument = argument
_wrapperDelegate = wrapperDelegate
End Sub
Private Function InnerPredicate(ByVal item As T) As Boolean
Return _wrapperDelegate(item, _argument)
End Function
Public Shared Widening Operator CType( _
ByVal wrapper As PredicateWrapper(Of T, A)) _
As Predicate(Of T)
Return New Predicate(Of T)(AddressOf wrapper.InnerPredicate)
End Operator
End Class
To use this class in your VB.NET code:
Sub Main()
Dim developers As New List(Of String)
developers.Add("Paul Stovell")
developers.Add("Bill Gates")
Dim greatDeveloperFirstName as string = "Paul"
Dim greatDevelopers As List(Of String) = developers.FindAll(_
New PredicateWrapper(Of String, String)( _
greatDeveloperFirstName, _
AddressOf IsGreatDeveloper))
For Each greatDeveloper As String In greatDevelopers
Console.WriteLine(greatDeveloper)
Next
Console.ReadKey()
End Sub
Note that you can now pass arguments to your "FindAll" predicate :)
Function IsGreatDeveloper(ByVal item As String, ByVal argument As String) As Boolean
Return item.StartsWith(argument)
End Function