在C#中使用Action 作为参数(模仿函数指针)

我需要编写一个委托函数,可以围绕基本的UDP调用“包裹”一些/ try / catch代码来validation链接。 我为Func工作了一个没有参数的函数,但我不能让它适用于Action,它有一个参数(但没有返回)。 在没有编译器抱怨的情况下,我似乎无法以逻辑方式传递参数。

我错了吗? 我是C#的新手,我基本上试图模仿函数指针的想法。 我不应该重载这个function吗? 我知道你不能重载代表(我认为这就是Func和Action存在的原因)。

这有效:

protected TResult udpCommand(Func command) { TResult retValue = default(TResult); while (!linkDownFail) { try { retValue = command(); break; } catch { LinkStateCallBack(ip, getLinkStatus()); if (linkDownFail) throw new LinkDownException(); Thread.Sleep(100); } } return retValue; } 

但这不是:

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

调用约定(适用于一个):

 udpCommand(someUdpCommand); 

如果您希望它足够通用以处理任意数量的参数,请尝试使用非genericsAction委托:

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

在C#3.0中,您可以这样调用它:

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

在C#2.0中,它有点丑陋:

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

这为您提供了延迟执行,而不会将您锁定到特定的方法签名中。

编辑

我只是注意到我有点偷走了Marc Gravell的评论……道歉Marc。 要回答如何减少重复,可以让Action方法调用Func方法,如下所示:

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

我相信(我可能错了)返回0并不比(隐含地)返回void更昂贵,但我可能会离开这里。 即使它确实有成本,它只会在堆栈上额外添加一个小小的有点特征。 在大多数情况下,额外的费用不会让你感到悲伤。

你的意思是:

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

随叫:

 udpCommand(someUdpCommand, arg); 

请注意,这可能更适用于C#3.0,它具有比C#2.0更强的generics类型推断。

我想你只需要在’命令’之后取出(T值)。

你想这样做……

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

然后它会像这样工作……

 public void ActionWithInt( int param ) { // some command } Action fp = ActionWithInt; udpCommand( fp, 10 ); // or whatever.