我需要编写一个委托函数,它可以围绕基本的UDP调用“包装”/ try / catch代码以验证链接。 我让Func为一个没有参数的函数工作,但我不能让它适用于Action,它有一个参数(但没有返回)。在没有编译器抱怨的情况下,我似乎无法以逻辑方式传递参数。
我是否认为这一切都错了?我是C#的新手,我基本上试图模仿函数指针的想法。我不应该重载这个功能吗?我知道你不能重载代表(我认为这就是Func和Action存在的原因)。
这有效:
protected TResult udpCommand<TResult>(Func<TResult> 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<T>(Action<T> command(T value))
{
while(!linkDownFail)
{
try
{
command(value);
break;
}
catch
{
LinkStateCallBack(ip, getLinkStatus());
if (linkDownFail) throw new LinkDownException();
Thread.Sleep(100);
}
}
return;
}
调用约定(对于有效的约定):
udpCommand<uint>(someUdpCommand);
答案 0 :(得分:10)
如果您希望它足够通用以处理任意数量的参数,请尝试使用非通用的Action委托:
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<T>
方法,如下所示:
protected void udpCommand(Action command)
{
udpCommand(() => { command(); return 0; });
}
我相信(我可能错了)返回0并不比(隐含地)返回void更昂贵,但我可能会离开这里。即使它确实有成本,它只会在堆栈上额外添加一个小小的笨拙的模特。在大多数情况下,额外的费用不会让你感到悲伤。
答案 1 :(得分:4)
你的意思是:
protected void udpCommand<T>(Action<T> command, T value) {...}
致电:
udpCommand(someUdpCommand, arg);
请注意,这可能在C#3.0上运行得更好,C#3.0具有比C#2.0更强的泛型类型推断。
答案 2 :(得分:2)
我认为你只需要在'命令'之后取出(T值)。
答案 3 :(得分:0)
你想这样做......
protected void udpCommand<T>(Action<T> command, T value)
{
while(!linkDownFail)
{
try
{
command(value);
// etc.
}
}
}
那么它会像这样工作......
public void ActionWithInt( int param )
{
// some command
}
Action<int> fp = ActionWithInt;
udpCommand<int>( fp, 10 ); // or whatever.