Using Action as an argument in C# (mimicking a function pointer)

后端 未结 4 761
眼角桃花
眼角桃花 2021-02-06 08:05

I need to write a delegate function that can \'wrap\' some while/try/catch code around a basic UDP call to verify the link. I made it work for Func for a function that has no ar

相关标签:
4条回答
  • 2021-02-06 08:11

    If you want this to be generic enough to handle any number of arguments, try using the non-genernic Action delegate:

    protected void udpCommand(Action command)
    {
        while(!linkDownFail)
        {
            try
            {
                command();
                break;
            }
            catch
            {
                LinkStateCallBack(ip, getLinkStatus());
                if (linkDownFail) throw new LinkDownException();
                Thread.Sleep(100);
            }
        }
        return;
    }
    

    In C# 3.0, you can call it like this:

    udpCommand(() => noParameterMethod());
    udpCommand(() => singleParameterMethod(value));
    udpCommand(() => manyParameterMethod(value, value2, value3, value4));
    

    In C# 2.0 it's a little uglier:

    udpCommand(delegate { noParameterMethod(); });
    udpCommand(delegate { singleParameterMethod(value); });
    udpCommand(delegate { manyParameterMethod(value, value2, value3, value4); });
    

    This gives you deferred execution without locking you into a particular method signature.

    EDIT

    I just notice I kinda stole Marc Gravell's comment... apologies Marc. To answer how you might reduce your duplication, you can have the Action method call the Func<T> method, like this:

    protected void udpCommand(Action command)
    {
        udpCommand(() => { command(); return 0; });
    }
    

    I believe (and I may be wrong) that returning 0 is no more costly than (implicitly) returning void, but I may be way off here. Even it it does have a cost, it would only put a tiny itty bitty snoodge extra on the stack. In most cases, the additional cost won't ever cause you any grief.

    0 讨论(0)
  • 2021-02-06 08:11

    I think you just need to take out the (T value) after 'command'.

    0 讨论(0)
  • 2021-02-06 08:28

    Are you trying to do this ...

    protected void udpCommand<T>(Action<T> command, T value)
    {
       while(!linkDownFail)
       {
        try                
        {
          command(value);
          // etc.
        }
      }
    }
    

    Then it would work like this ...

    public void ActionWithInt( int param )
    {
       // some command
    }
    
    Action<int> fp = ActionWithInt;
    
    udpCommand<int>( fp, 10 );  // or whatever.
    
    0 讨论(0)
  • 2021-02-06 08:33

    Do you mean:

        protected void udpCommand<T>(Action<T> command, T value) {...}
    

    With calling:

    udpCommand(someUdpCommand, arg);
    

    Note that this may work better on C# 3.0, which has stronger generic type inference than C# 2.0.

    0 讨论(0)
提交回复
热议问题