Using generics in dotnet for functions with any number of arguments?

I would like to have a function that can "wrap" any other function call. In this particular case, it would allow me to write more general transaction processing around some specific operations.

I can write this for any specific number of arguments, eg. for one argument:

Public Shared Sub WrapFunc(Of T)(ByVal f As Action(Of T), ByVal arg As T)
    ' Test some stuff, start transaction
    f(arg)
    ' Test some stuff, end transaction
End Sub

      

... but I was hoping that this handle would have any number of arguments without having duplicate code for 0 args, 1 arg, 2 args, etc.

Is there a way to do this?

[Edit] Thanks to Robert Fraser for the C # code. For reference, here's the VB translation:

[Edit2] Corrected code. Unfortunately, it looks like there is no way to use separate ActAsFunc functions in vb. On the positive side, they are hidden from everyone using the closure, and closures are reused.

Public Shared Sub WrapFunc(ByVal f As Action)
    _WrapFunc(f)
End Sub
Public Shared Sub WrapFunc(Of T1)(ByVal f As Action(Of T1), ByVal arg1 As T1)
    _WrapFunc(Closure(f, arg1))
End Sub
Public Shared Sub WrapFunc(Of T1, T2)(ByVal f As Action(Of T1, T2), ByVal arg1 As T1, ByVal arg2 As T2)
    _WrapFunc(Closure(f, arg1, arg2))
End Sub

Private Shared Sub _WrapFunc(ByVal f As Action)
    ' Test some stuff, start transaction
    f()
    ' Test some stuff, end transaction
End Sub

Private Shared Function Closure(Of T1)(ByVal f As Action(Of T1), ByVal arg1 As T1) As Action
    Return New Action(Function() _ActAsFunc(f, arg1))
End Function
Private Shared Function Closure(Of T1, T2)(ByVal f As Action(Of T1, T2), ByVal arg1 As T1, ByVal arg2 As T2) As Action
    Return New Action(Function() _ActAsFunc(f, arg1, arg2))
End Function

Private Shared Function _ActAsFunc(Of T1)(ByVal f As Action(Of T1), ByVal arg1 As T1) As Object
    f(arg1) : Return Nothing
End Function
Private Shared Function _ActAsFunc(Of T1, T2)(ByVal f As Action(Of T1, T2), ByVal arg1 As T1, ByVal arg2 As T2) As Object
    f(arg1, arg2) : Return Nothing
End Function

      

+2


a source to share


3 answers


Nope. I would also like it to be; I do this all the time.

Internally MS uses text templates / code generation tools to generate repetitive code. A parameter in C # is to create closures around the arguments and then simply pass them to another function as no argument to System.Action; I'm not sure if VB.NET supports this.



This is what I am doing in C #; hopefully someone with VB.NET experience can translate this:

public void add(Action action, EventFlags flags) { addInternal(action, flags); }
public void add<T1>(Action<T1> action, T1 p1, EventFlags flags) { addInternal(closure(action, p1), flags); }
public void add<T1, T2>(Action<T1, T2> action, T1 p1, T2 p2, EventFlags flags) { addInternal(closure(action, p1, p2), flags); }
public void add<T1, T2, T3>(Action<T1, T2, T3> action, T1 p1, T2 p2, T3 p3, EventFlags flags) { addInternal(closure(action, p1, p2, p3), flags); }
public void add<T1, T2, T3, T4>(Action<T1, T2, T3, T4> action, T1 p1, T2 p2, T3 p3, T4 p4, EventFlags flags) { addInternal(closure(action, p1, p2, p3, p4), flags); }

private static Action closure<T1>(Action<T1> action, T1 p1) { return () => action(p1); }
private static Action closure<T1, T2>(Action<T1, T2> action, T1 p1, T2 p2) { return () => action(p1, p2); }
private static Action closure<T1, T2, T3>(Action<T1, T2, T3> action, T1 p1, T2 p2, T3 p3) { return () => action(p1, p2, p3); }
private static Action closure<T1, T2, T3, T4>(Action<T1, T2, T3, T4> action, T1 p1, T2 p2, T3 p3, T4 p4) { return () => action(p1, p2, p3, p4); }

      

+2


a source


I haven't tried this with Generics, but what about ParamArray ?



Public Shared Sub WrapFunc(Of T)(ByVal f As Action(Of T()), ByVal ParamArray args() As T)
    ' Test some stuff, start transaction
    f(args)
    ' Test some stuff, end transaction
End Sub

      

0


a source


Can't you use ParamArray?

  Public Shared Sub WrapFunc(Of T)(ByVal f As Action(Of T), ByVal ParamArray args() As T)
        ' Test some stuff, start transaction
        For Each arg As T In args
            f(arg)
        Next

        ' Test some stuff, end transaction
    End Sub

      

0


a source







All Articles