views:

292

answers:

2

I find myself calling functions from lambdas frequently as the provided delegate does not match or does not have sufficient parameters. It is irritating that I cannot do lambda on subroutines. Each time I want to do this I have to wrap my subroutine in a function which returns nothing. Not pretty, but it works.

Is there another way of doing this that makes this smoother/prettier?

I have read that this whole lambda inadequacy will probably be fixed in VS2010/VB10 so my question is more out of curiosity.

A simple Example:

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
A: 

It IS fixed in VB10, the VS10 Beta is available, if it's an option for you to use it. In VB10 you have lambdas without a return value, and inline subs/functions.

For now, maybe you could just forget lambdas and work with delegates instead? Something like:

processingClass.ProcessList(AddressOf ProcessingSub)
Meta-Knight
well as stated in the question the issue was when the delegate spec does not match the implementation. Calling `processingClass.ProcessList(AddressOf ProcessingSub)` would yield a compile-time error as `ProcessingSub(ByVal index As Integer, ByRef result As Integer)` does not match the delegate `ProcessData(ByVal index As Integer)`
Tewr
Can't you just add the byref result to the ProcessData parameters, and send the result in the ProcessList function?
Meta-Knight
Well the point is that ProcessingClass should not have to know how I implement ProcessData. Otherwise, the whole point of having a delegate would be lost. I guess I oversimplified my example. A realistic ProcessData delegate should take some kind of datastructure as an argument. And in different situations, I have different implementations of ProcessData, with different arguments, while processingClass stays happily unaware of what goes on inside...
Tewr
+1  A: 

If you find that you are doing it too often and generally with the same type of data, you can wrap the delegate in a class.

Create a base class that converts to the delegate:

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

Inherit from the 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

Use it:

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
Wilhelm
Seeing your solution makes me realize that I'm actually tring to maintain state, which of course should be done with a class. And with your solution the arguments to the delegate are no longer important, which makes it even prettier.
Tewr