代表:如何在VB.NET中理解它们?

时间:2011-05-31 02:46:37

标签: vb.net

我希望更好地了解代表。我已经查看了MSDN和其他各种网站上的示例,但我只是不“得到”它们。我知道它们实际上类似于指向C中函数的指针。但由于某种原因,C语法在使用这样的结构时更加清晰。

所以我开发了一个场景来尝试使用委托,或者至少我认为这样的用法是有效的。假设下面的代码属于某种类,并且MyObj具有类型为String的Name属性,返回与对象相同的小写名称(即{{1} }):

Obj1.Name = "obj1"


这是你的基本O(N)“搜索匹配的东西的列表并在找到时返回索引”。如果我使用Private Shared MyList As New List(Of MyObj)(Obj1, Obj2, Obj3, Obj4, Obj5, Obj6) Private Shared Function FindObj(ByVal obj As MyObj, ByVal name As String) As Boolean Return String.Equals(obj.Name, name, OrdinalIgnoreCase) End Function Friend Shared Sub RedOctober() Dim obj4Pos As Int32 = -1 For i As Int32 = 0 to (MyList.Count - 1) Step 1 If FindObj(MyList(i), "obj4") Then obj4Pos = i Exit For End If Next i If obj4Pos <> -1 Then Debug.Print("Found obj4!") Else Debug.Print("Couldn't find obj4! :(") End If End Sub ,我可以将其推断为“更好”的东西,但是:

FindIndex


问题是,如果我想搜索的不仅仅是obj4,该怎么办?如果我以这种方式使用Private Shared MyList As New List(Of MyObj)(Obj1, Obj2, Obj3, Obj4, Obj5, Obj6) Friend Shared Sub RedOctober() Dim obj4Pos As Int32 = MyList.FindIndex( Function(o) String.Equals(obj.Name, "obj4", OrdinalIgnoreCase)) If obj4Pos <> -1 Then Debug.Print("Found obj4!") Else Debug.Print("Couldn't find obj4! :(") End If End Sub ,我需要一个专门的lambda表达式/匿名函数,用于我想找到的FindIndex的每个对象。这会在生成的二进制文件中添加额外的函数/ subs,每个函数都执行大致相同的操作,因此它很臃肿。

这就是我知道委托可以使用的地方如果我保留我的MyObj函数并以某种方式在委托中引用它,传递一个不同的字符串,依赖于我想在FindObj中找到的对象。问题是,MyList需要FindIndex,而我的System.Predicate(Of T)函数需要两个参数:检查FindObj属性的对象和要检查的字符串。

我的问题是:

  1. 对于代表来说,这是适当的情况吗?
  2. 与使用直接Name循环相比,它会更快/更好/更有效/更清洁/挑剔吗?
  3. 这是否可行,通过纯lambda表达式,我可以传递我的两个For参数并找到正确的对象,而不是声明多个类似性质的lambda(因此,添加膨胀)。
  4. FindObj不是Linq的事情,但有没有一种方法使用Linq完成相同的任务可能更好(在效率方面 - 是的,我是一个优化坚果,不,我不会为它道歉)?
  5. 使用VB.NET(通常是.NET)的游戏通常有多种方法来完成任务。困难的部分是找到适应特定情况的方式,不是不必要的膨胀或缓慢,并且对于其他人来说可以读取代码(或者在2-3个月的中断之后)。

    对于我怀疑的人来说,这应该是一个简单的方法。如果我在我的例子中犯了任何错误,请随意指出并笑:)

1 个答案:

答案 0 :(得分:2)

要扩展您的第二个示例,您可以执行此操作:

Private Shared MyList As New List(Of MyObj)(Obj1, Obj2, Obj3, Obj4, Obj5, Obj6)        

Friend Shared Sub RedOctober(toFind as String)
    Dim obj4Pos As Int32 = MyList.FindIndex(
        Function(o) String.Equals(o.Name, toFind, OrdinalIgnoreCase))

    If obj4Pos <> -1 Then
        Debug.Print("Found " & toFind & "!")
    Else
        Debug.Print("Couldn't find " & toFind & "! :(")
    End If
End Sub

FindIndex的参数是一个lambda,它能够捕获声明范围内的变量。这使您可以“传入”字符串进行搜索,而不会将其作为匿名函数的参数。

委托基本上是对方法的引用。该方法可以是类,匿名函数或lambda中的成员方法。谓词(T)只是一个预定义的委托类型,它将访问接受对方法或lambda的引用,无论哪个更适合上下文。

明确回答您的问题:

  1. Predicate(Of T)只是一个预定义的委托类型。无论您传递给FindIndex()的是什么,都必须能够转换为此类型。这可以是对方法或lambda的引用。

  2. 在这种情况下,可能不会。

  3. 请参阅上面的代码。

  4. FindIndexList(Of T)上定义,这是您在此处理的内容。从理论上讲,它将针对Linq运营商可能没有的List实现进行优化。 Linq代码看起来几乎一样,并且应该具有相似的性能,但是如果你知道你正在使用List那么你可能最好坚持使用本机方法,就像你在这里做的那样。

  5. <强>更新

    我现在理解您希望RedOctober使用您的FindObj方法。试试这个:

    Friend Shared Sub RedOctober()
        Dim obj4Pos As Int32 = MyList.FindIndex(
            Function(o) FindObj(o, "obj4"))
    
        If obj4Pos <> -1 Then
            Debug.Print("Found obj4!")
        Else
            Debug.Print("Couldn't find obj4! :(")
        End If
    End Sub