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 arguments, but I can't make it work for Action, which has an argument (but no return). I can't seem to pass in the argument in a logical way without the compiler complaining.
Am I going about this all wrong? I'm new to C# and I'm essentially trying to mimick the idea of a function pointer. Should I not be overloading this function? I know you can't overload delegates (I assume that's why Func and Action exist).
This works:
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;
}
But this does not:
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;
}
Calling convention (for one that works):
udpCommand<uint>(someUdpCommand);
If you want this to be generic enough to handle any number of arguments, try using the non-genernic Action delegate:
In C# 3.0, you can call it like this:
In C# 2.0 it's a little uglier:
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 theFunc<T>
method, like this: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.
Are you trying to do this ...
Then it would work like this ...
I think you just need to take out the (T value) after 'command'.
Do you mean:
With calling:
Note that this may work better on C# 3.0, which has stronger generic type inference than C# 2.0.