2012-01-27 15 views
5

我有一個內嵌的lambda表達式,我希望在整個應用程序中使用它。我似乎無法找到有關如何使用比被測試元素更多的參數來做到這一點的參考。這是我目前擁有的一個簡單例子。我可以使用方法而不是帶有額外參數的Lambda表達式

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 

我知道IEnumerable.Where接受與元素類型作爲參數和返回布爾值的方法。

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 

我想將Search變量也傳遞給FindName。我似乎無法使語法達到此目的。我提出的唯一工作解決方案是將所有內容都傳遞給一個函數來執行原始語句。

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 

不覺得有義務在VB中回答。

+0

縮短我的[委託方式(http://stackoverflow.com/a/9036948/284240)。 – 2012-01-30 12:59:13

回答

6

與lambda表達式的好處是,他們允許關閉自動捕獲屬於本地變量你的範圍。例如(原諒C#):

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

在上面的代碼中,Search變量實際上是被封裝在閉合。如果你想只是傳遞一個方法,你必須模擬一下瓶蓋做一個實際的階級結構:

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); 

然而,這種策略只是案件的一小部分是有用的。我發現通常最好使用一個lambda表達式,將適當的變量傳遞給完成所有工作的函數。

1

我會用一個擴展方法: -

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 
+0

再次閱讀你的問題我不是100%確定這是你實際上後? – pingoo 2012-01-27 16:27:35

+0

到目前爲止,在閱讀答案後,我所追求的內容可能不存在。但擴展將清理單獨的功能,所以在我的情況下,擴展將運行良好。 – 2012-01-27 19:18:03

-1

我不認爲你可以在更多的參數傳遞給Where方法,但你可以設置搜索參數作爲類成員將FindName方法可以訪問。例如(我會在C#寫這因爲這是我比較熟悉):

string search = "Ken"; 

private void Test() 
{ 
    var list = new List<string>() { "Joe", "Ken", "Bob", "John" }; 
    // Set search member to whatever you need before calling query 
    search = "Joe"; 
    var result = list.Where(FindName); 
} 

private bool FindName(string name) 
{ 
    // Predicate method will compare against whatever class member is set to 
    return name == search; 
} 
+1

這是不好的做法。您正在使用全局狀態來解決本地問題。這很容易導致問題。如果您返回結果,例如您無法控制查詢實際執行的時間,同時變量可能會發生變化。同樣的問題,如果你有多個線程。直接使用LINQ或其他推薦的擴展方法。 – aKzenT 2012-01-27 16:50:35

+0

想通過你所說的話,我可以看到你的意思,現在同意你的觀點,也不會在多線程環境下工作。 – 2012-01-27 17:35:25

0

你可以使用一個Func(Of T, TResult) Delegate即使有多個參數:

Dim names = {"Joe", "Ken", "Bob", "John", "Otto"} 
Dim matchesPattern As Func(Of String, String, Boolean) = 
    Function(input, searchPattern) input Like searchPattern 
Dim results = names.Where(Function(name) matchesPattern(name, "?o*")) 
' returns "Joe", "Bob" and "John" ' 
相關問題