Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can I use a Method instead of Lambda expression with extra parameters

Tags:

c#

.net

vb.net

I have an inline lambda expression that I would like to use throughout my application. I just can't seem to find a reference on how to do this with more parameters than the element being tested. Here is a quick example of what I currently have.

Private Sub Test()
    Dim List As New List(Of String) From {"Joe", "Ken", "Bob", "John"}
    Dim Search As String = "*Jo*"
    Dim Result = List.Where(Function(Name) Name Like Search)
End Sub

I know the IEnumerable.Where accepts a method with the element type as a parameter and a returning boolean.

Private Sub Test()
    Dim List As New List(Of String) From {"Joe", "Ken", "Bob", "John"}
    Dim Search As String = "*Jo*"
    Dim Result = List.Where(AddressOf FindName)
End Sub

Private Function FindName(Name As String) As Boolean
    Return Name Like "*Jo*"
End Function

I would like to pass the Search variable into FindName as well. I just can't seem to get the syntax figured accomplish this. The only working solution I've come up with is passing everything to a function to perform the original statement.

Private Sub Test()
    Dim List As New List(Of String) From {"Joe", "Ken", "Bob", "John"}
    Dim Search As String = "*Jo*"
    Dim Result = FindName(List, Search)
End Sub

Private Function FindName(List As IEnumerable(Of String), Search As String) As IEnumerable(Of String)
    Return List.Where(Function(Name) Name Like Search)
End Function

Don't feel obligated to answer in VB.

like image 907
Joshua C Avatar asked Jan 27 '12 16:01

Joshua C


2 Answers

The nice thing with lambda expressions is that they allow closures to automatically capture variables that are local to your scope. For example (pardon the C#):

List.Where(i => FindName(i, Search));

In the above code, the Search variable is actually being encapsulated in a closure. If you want to just pass a method, you'll have to simulate what closures do with an actual class structure:

public class NameFinder
{
    private string _search;
    public NameFinder(string search) {
        _search = search;
    }
    public bool Match(string item) {
        // C# equivalent of "return item LIKE _search"
    }
}

// Usage
var nameFinder = new NameFinder(Search);
List.Where(nameFinder.Match);

However, this strategy is only useful in a small subset of cases. I find it's usually best to just use a lambda expression that passes the appropriate variables into the function that does all the work.

like image 119
StriplingWarrior Avatar answered Nov 15 '22 04:11

StriplingWarrior


I would use an extension method:-

Module Module1

    Sub main()
        Dim List As New List(Of String) From {"Joe", "Ken", "Bob", "John"}
        Dim Search As String = "*Jo*"
        Dim Result = List.FindName(Search)
    End Sub


End Module

Public Module Extensions

    <System.Runtime.CompilerServices.Extension()>
    Public Function FindName(List As IEnumerable(Of String), Search As String) As IEnumerable(Of String)

        Return List.Where(Function(Name) Name Like Search)

    End Function

End Module
like image 30
pingoo Avatar answered Nov 15 '22 03:11

pingoo