1

Can I reduce the number of methods needed in my class to accomplish running code in a lambda, with optional parameters?

I created a class where I can run code repeatedly like this:

Scheduler.InvokeRepeated(1.0f, () => { ... // Do things forever });

I also want to be able to easily cancel a running code like this:

Scheduler.InvokeRepeated(1.0f, (runningAction) => {
    ... // Do things for a while
    if (exit) {
        runningAction.Cancel();
    }
});

But I don't want to force the user to specify that runningAction parameter. So this is my class:

    public static RunningAction InvokeRepeated(float interval, Action action)
    {
        // Call InvokeAt with an "action" parameter.
        return InvokeAt(currentTime + interval, interval, action, null);
    }

    public static RunningAction InvokeRepeated(float interval, Action<RunningAction> actionWithParam)
    {
        // Call InvokeAt with an "actionWithParam" parameter.
        return InvokeAt(currentTime + interval, interval, null, actionWithParam);
    }

    private static RunningAction InvokeAt(float time, float interval, Action<> action, Action<RunningAction> actionWithParam)
    {
        ... // Do things depending on whether action is null or actionWithParam is null
    }

Now imagine that I have a lot of methods for specifying a first delay, and then an interval. Or just something that runs delayed once, or twice, and doesn't repeat etc.

So that means I have to duplicate every method to include these two different kinds of 'Action's. But if possible I'd rather just have one method.

I tried creating my own delegate, instead of using Action:

    public delegate void MyDelegate(RunningAction arg = null);

But that didn't allow me to call it without specifying a parameter.

Could you also point me to where I can read up on stuff like this? Weird things you can and can't do with generics and delegates?

Daniel Johansson
  • 740
  • 6
  • 10
  • No, that's not possible. A delegate points to exactly **one** function. An overloaded function however is not **a single function**, but two. So to which of them should the delegate point? – MakePeaceGreatAgain Sep 09 '22 at 09:03
  • What is it you are really trying to do? And what library are you using? Normally if you have an optional argument for things like cancellation or progress, you would use a dummy value when it is not needed, like `CancellationToken.None`. But if you want to do something periodically you would normally use a *timer*, that makes it trivial to just stop the timer when you are done. – JonasH Sep 09 '22 at 09:07
  • I'm using Unity3D, and I created my own library for scheduling tasks in the different stages of Unity's lifecycle: Update(), LateUpdate(), BeforeRender(), EndOfFrame() etc. I'm trying to allow the user to easily cancel their tasks, without making a reference to the task on the line before scheduling it. So they could optionally specify a parameter in the lambda that would allow them to easily cancel it. Otherwise that parameter would simply be null, and invisible. – Daniel Johansson Sep 09 '22 at 09:18
  • Also, unfortunately, the duplicated question didn't help. Their use-case worked but this doesn't work: delegate void SimpleDelegate(bool x = true); static void Foo(SimpleDelegate s) { s.Invoke(); } static void Main() { Foo(() => { print(t); }); } – Daniel Johansson Sep 09 '22 at 09:31
  • Why are you not just declaring and using InvokeWhatever methods with an `Action` delegate only? You would then write the lambdas that don't care about the RunningAction parameter like for example: `Scheduler.InvokeRepeated(1.0f, _ => { ... // Do things forever });` –  Sep 09 '22 at 09:34
  • It's probably some kind of syntax OCD, coming from Java. I hate the _ character. It's a great idea that I'll have to get accustomed to, though. Thanks! – Daniel Johansson Sep 09 '22 at 09:44

0 Answers0