20

I have class that performs many similar yet different read/write operations to an excel file. All of these operations are defined in separate functions. They all have to be contained within the same long block of code (code that checks and opens a file, saves, closes, etc). What is reasonable way to not have to duplicate this code each time? The problem is that I can't just one method containing all of the shared code before I execute the code that is different for each method because that code must be contained within many layers of if, try, and for statements of the shared code.

Is it possible to pass a function as a parameter, and then just run that function inside the shared code? Or is there a better way to handle this?

Christopher Bottoms
  • 11,218
  • 8
  • 50
  • 99
Bernoulli Lizard
  • 537
  • 1
  • 12
  • 23
  • possible duplicate of [How to Pass MethodName as Parameter of a Procedure in VBNET](http://stackoverflow.com/questions/8697504/how-to-pass-methodname-as-parameter-of-a-procedure-in-vbnet) – mbomb007 Apr 13 '15 at 18:30

3 Answers3

39

Focusing on the actual question:

Is it possible to pass a function as a parameter

Yes. Use AddressOf TheMethod to pass the method into another method. The argument type must be a delegate whose signature matches that of the target method. Inside the method, you treat the parameter as if it were the actual method. Example:

Sub Foo()
    Console.WriteLine("Foo!")
End Sub

Sub Bar()
    Console.WriteLine("Bar!")
End Sub

Sub CallSomething(f As Action)
    f()
End Sub

' … somewhere:
CallSomething(AddressOf Foo)
CallSomething(AddressOf Bar)

As I said, the actual parameter type depends on the signature of the method you’d like to pass. Use either Action(Of T) or Func(Of T) or a custom delegate type.

However, in many cases it’s actually appropriate to use an interface instead of a delegate, have different classes implement your interface, and pass objects of those different classes into your method.

Konrad Rudolph
  • 530,221
  • 131
  • 937
  • 1,214
9

Declare your parameter as Func(Of T) or Action(Of T).

Which one you should use depend on your methods signature. I could give you more precise answer if you gave us one.

MarcinJuraszek
  • 124,003
  • 15
  • 196
  • 263
  • If I declare as Func, I get the error "type func is not defined". If I declare as Action, I get the error "to few type arguments to system.action(of T)". Some of the methods that I would pass are functions, some of them are subs. – Bernoulli Lizard Oct 21 '13 at 16:12
  • They have to have the same signature to use either `Func(Of T)` or `Action(Of T)`. – MarcinJuraszek Oct 21 '13 at 16:46
  • What does the *called* subroutine's signature look like? Is the Action(of T) passed ByRef or ByVal? I am getting error "All parameters must be expicitly typed if any of them is explicitly typed". Do I understand correctly that an Action, if passed, must be the only parameter passed? – Tim Jul 08 '16 at 17:25
  • @Tim `Action` is equivalent to a `Sub` and `Func` is equivalent to `Function`. As far as the Parameter's, it depends on how you define them in the definition of the method. I would suggest making them ByVal, will lead to less confusion, as you are not explicitly calling the method and cannot guarantee the condition of the value at the time of execution since this is using a Reflection framework to execute. – GoldBishop Dec 02 '16 at 21:46
4

You can also use a delegate so you can pass function/subs that have a certain signature.

Steve
  • 5,585
  • 2
  • 18
  • 32