Does passing an Action as a parameter create garbage?

I’m using a “timer” script that takes an action as a parameter. The script calls the Action when the timer is complete. Does passing an action in a parameter create garbage? I use this a lot and im getting a bunch of GC.Collect() calls in the profiler and it’s coming from my timer classes.

Here’s what it looks like:

public class Timer : MonoBehaviour
{
    private float _timer;
    private float _maxTime;
    public void StartTimer(float time, Action callback) 
    { 
         _timer = 0;
        _maxTime = time;
        TimerCompleteCallback = callback;  
    }
    ////////// Some update code //////////////////////
    void TimerEnd() 
    {  
        this.enabled = false;
        TimerCompleteCallback();
    }
}

public class OtherClass : MonoBehaviour
{
     private Timer _timer;
     void Start()
     {
         _timer = gameObject.AddComponent<Timer>();
         _timer.StartTimer(5, OnTimerComplete);
     }
                
    void OnTimerComplete()
    {
        // Will this timer loop end up creating garbage?
        _timer.StartTimer(5, OnTimerComplete);
    }
}

Fun! Here is your issue:

_timer.StartTimer(5, OnTimerComplete);

This seems to be inlined to be:

_timer.StartTimer(5, () => OnTimerComplete);

Therefore this is creating a new delegate each time you start the timer. If you cache the delegate this is solved:

public class OtherClass : MonoBehaviour
{
      private Timer _timer;
      private Action _action;

      void Start()
      {
          _timer = gameObject.AddComponent<Timer>();
         _action = OnTimerComplete;
          _timer.StartTimer(5, _action);
      }
                 
     void OnTimerComplete()
     {
         // Will this timer loop end up creating garbage?
         _timer.StartTimer(5, _action);
     }
 }

Hope this helps!

For reference, here is my test:

using System;
using UnityEngine;

public class ActionDelegateGarbageTest : MonoBehaviour
{
    private Action mAction;

    public void Start ()
    {
        mAction = () => EventReciever ();
    }

    public void Update ()
    {
        //doesn't create garbage
        //PassTest (mAction);

        //creates garbage
        //PassTest (EventReciever);
    }

    private void PassTest (Action actionToComplete)
    {
        actionToComplete();
    }

    private void EventReciever()
    {
        
    }
}