【问题标题】:Calling Subroutines from lambda in vb.net在 vb.net 中从 lambda 调用子例程
【发布时间】:2009-10-07 07:27:56
【问题描述】:

我发现自己经常从 lambda 调用函数,因为提供的委托不匹配或没有足够的参数。令人恼火的是,我不能对子程序执行 lambda。每次我想这样做时,我都必须将我的子例程包装在一个不返回任何内容的函数中。不漂亮,但它有效。

是否有另一种方法可以使这更流畅/更漂亮?

我已经读到整个 lambda 不足可能会在 VS2010/VB10 中得到修复,所以我的问题更多是出于好奇。

一个简单的例子:

Public Class ProcessingClass
    Public Delegate Sub ProcessData(ByVal index As Integer)
    Public Function ProcessList(ByVal processData As ProcessData)
        ' for each in some list processData(index) or whatever'
    End Function
End Class

Public Class Main

    Private Sub ProcessingSub(ByVal index As Integer, _
                              ByRef result As Integer)
        ' (...) My custom processing '
    End Sub

    Private Function ProcessingFunction(ByVal index As Integer, _
                                        ByRef result As Integer) As Object
        ProcessingSub(index, result)
        Return Nothing
    End Function

    Public Sub Main()
        Dim processingClass As New ProcessingClass
        Dim result As Integer
        ' The following throws a compiler error as '
        ' ProcessingSub does not produce a value'
        processingClass.ProcessList( _
            Function(index As Integer) ProcessingSub(index, result))
        ' The following is the workaround that'
        ' I find myself using too frequently.'
        processingClass.ProcessList( _
            Function(index As Integer) ProcessingFunction(index, result))
    End Sub

End Class

【问题讨论】:

    标签: vb.net delegates lambda


    【解决方案1】:

    如果你发现你经常这样做并且通常使用相同类型的数据,你可以将委托包装在一个类中。

    创建一个转换为委托的基类:

    Public MustInherit Class ProcessDataBase
        Public Shared Widening Operator CType(operand As ProcessDataBase) as ProcessingClass.ProcessData
            Return AddressOf operand.Process
        End Sub
    
        Protected MustOverride Sub Process(index As Integer)  
    End Class
    

    从类继承:

    Public Class ProcessResult
        Inherits ProcessDataBase
    
        Public Result As Integer
    
        Protected Overrides Sub Process(index as Integer)
            ' Your processing, result is modified.
        End SUb
    End Class
    

    使用它:

    Public Class Main()
        Public Sub Main()
            Dim processingClass As New ProcessingClass
            Dim processor As New ProcessResult
    
            processingClass.ProcessList(processor)
            Dim result as integer=processor.Result
        End Sub
    End Class
    

    【讨论】:

    • 看到您的解决方案让我意识到我实际上是在努力维护状态,这当然应该通过课程来完成。使用您的解决方案,代表的参数不再重要,这使它更漂亮。
    【解决方案2】:

    它已在 VB10 中修复,VS10 Beta 为available,如果您可以选择使用它。在 VB10 中,您有没有返回值的 lambda,以及内联子/函数。

    现在,也许您可​​以忘记 lambda 并使用委托来代替?比如:

    processingClass.ProcessList(AddressOf ProcessingSub)
    

    【讨论】:

    • 正如问题中所述,问题是委托规范与实现不匹配。调用 processingClass.ProcessList(AddressOf ProcessingSub) 会产生编译时错误,因为 ProcessingSub(ByVal index As Integer, ByRef result As Integer) 与委托 ProcessData(ByVal index As Integer) 不匹配
    • 不能直接把byref结果加到ProcessData参数中,然后在ProcessList函数中发送结果吗?
    • 嗯,重点是 ProcessingClass 不应该知道我是如何实现 ProcessData 的。否则,就失去了委托的全部意义。我想我过分简化了我的例子。一个现实的 ProcessData 委托应该将某种数据结构作为参数。在不同的情况下,我有不同的 ProcessData 实现,具有不同的参数,而 processingClass 很高兴地不知道内部发生了什么......