0

Good day Gurus! Am trying to call a Sub that has parameter from another Sub using Action but not working. Please I have tried to solve this error but couldn't.

I have two Sub in my BasePage in ASP.Net as shown below;

Sub Check(mySub As Action)
    mySub()
End Sub
Sub TestMsg(g As String)
    MsgBox(g)
End Sub

And on click event LinkButton, am trying to call TestMsg through Check as below

Private Sub LinkButton1_Click(sender As Object, e As EventArgs) Handles LinkButton1.Click
    Check(AddressOf TestMsg("Call a sub from another"))
End Sub

But am getting an error message that says addressof operand must be the name of a method (without parenthesis)

Please what is the solution to this?

Thanks in advance

  • Why are you using WebForms in 2022? – Dai Feb 03 '22 at 21:21
  • `TestMsg` is not an `Action`. An `Action` delegate has no parameters. `TestMsg` is actually an `Action` (well... `Action(Of String)`). You should use a VB lambda-expression to invoke `TestMsg` with a string argument: https://learn.microsoft.com/en-us/dotnet/visual-basic/programming-guide/language-features/procedures/lambda-expressions – Dai Feb 03 '22 at 21:22
  • 1
    It is a local website that has been under used only trying to improved on some of the codes. Thanks – user14211563 Feb 03 '22 at 21:24

2 Answers2

1

You can get around it with a trick, but it feels like it defeats the purpose

Private Sub LinkButton1_Click(sender As Object, e As EventArgs) Handles LinkButton1.Click
    Check(Sub() TestMsg("Call a sub from another"))
End Sub

To make it work the way you want, you might make a generic overload and call that

Sub Check(mySub As Action)
    mySub()
End Sub
Sub Check(Of T)(mySub As Action(Of T), arg As T)
    mySub(arg)
End Sub
Sub TestMsg(g As String)
    MsgBox(g)
End Sub

Private Sub LinkButton1_Click(sender As Object, e As EventArgs) Handles LinkButton1.Click
    Check(AddressOf TestMsg, "Call a sub from another")
End Sub

Still, it would be easier to just call

TestMsg("Call a sub from another")

You can use a different version of Action depending on the signatures of your method.

Sub Check(Of T)(mySub As Action(Of T, String, String), arg1 As T, arg2 As String, arg3 As String)

Or you can loosely use a single Action(Of Object()) to pass a varying number of arguments to a method, but you lose tight coupling. You'll need to trust that the caller has information about the requirements of args, such as in my example below, it requires an object, integer, double (or something which is castable to those). Inspired by this Q & A

Public Sub TestMsg(ParamArray args As Object())
    If args.Length > 0 Then
        Console.Write(args(0))
        If args.Length > 1 Then
            Dim i = CInt(args(1))
            Console.Write($", {i + 5}")
            If args.Length > 2 Then
                Dim d = CDbl(args(2))
                Console.Write($", {d / 2}")
            End If
        End If
        Console.WriteLine()
    End If
End Sub

Public Sub Check(mySub As Action(Of Object()), ParamArray args As Object())
    mySub(args)
End Sub

Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
    Check(AddressOf TestMsg, "With a string")
    Check(AddressOf TestMsg, "With a string and int", 1)
    Check(AddressOf TestMsg, "With a string, int, and double", 5, 123.45)
End Sub

With a string
With a string and int, 6
With a string, int, and double, 10, 61.725

djv
  • 15,168
  • 7
  • 48
  • 72
  • Thanks Djv. It worked perfectly. However, when I tried with more than one argument as this: Sub Check(Of T)(mySub As Action(Of T), arg1 As T, arg2 As String, arg3 As String) mySub(arg1, arg2, arg3) End Sub ----- I got error message that "too many arguments to action(of T)" – user14211563 Feb 04 '22 at 07:46
  • `Sub Check(Of T)(mySub As Action(Of T, String, String), arg1 As T, arg2 As String, arg3 As String)` – djv Feb 04 '22 at 17:26
  • Thanks it works just as expected – user14211563 Feb 05 '22 at 14:44
0

vb.net does have "CallByName" feature.

You can specify the sub you call by passing a string name.

So, say this code:

Protected Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click

   Dim strSubToCall As String

    strSubToCall = "Sub1"
    CallByName(Me, strSubToCall, CallType.Method)

    strSubToCall = "Sub2"
    CallByName(Me, strSubToCall, CallType.Method, "String value passed")

    strSubToCall = "Sub3"
    CallByName(Me, strSubToCall, CallType.Method, "String value passed", 55)



End Sub

Sub Sub1()

    Debug.Print("Sub 1 called")

End Sub

Sub Sub2(s As String)

    Debug.Print("Sub 2 called - value passed = " & s)

End Sub

Sub Sub3(s As String, i As Integer)

    Debug.Print("Sub 3 called, values passed = " & s & " - " & i.ToString)

End Sub

output:

Sub 1 called
Sub 2 called - value passed = String value passed
Sub 3 called, values passed = String value passed - 55
Albert D. Kallal
  • 42,205
  • 3
  • 34
  • 51