public static T CreateOrRecycle <T, K, C>(this IRecyclingContainer <T, K, C> @this, CreateWithContext <T, K, C> Create, K key, C context) where T : class, IRecyclable <T, K, C> where C : struct
    {
        var trash = @this.Trash;

        // If we don't have anything to recycle, just create a new one
        if (trash.Count == 0)
        {
            return(Create(key, context));
        }

        // Otherwise get the last one from the trash, and recycle it instead
        var lastIndex = trash.Count - 1;
        var obj       = trash[lastIndex];

        trash.RemoveAt(lastIndex);
        return(obj.Recycle(key, context));
    }
    public static bool RemoveOrThrowAway <T, K, C>(this IRecyclingContainer <T, K, C> @this, T obj) where T : class, IRecyclable <T, K, C> where C : struct
    {
        var trash = @this.Trash;

        // Should not happen
        if (trash.Contains(obj))
        {
            UnityEngine.Debug.LogError("Trying to remove item that's already removed");
            return(false);
        }

        // Try to destroy our object
        if (obj.CanDispose())
        {
            obj.Dispose();

            // While we're at it, try to clear all other trashObjects
            for (int t = trash.Count - 1; t >= 0; t--)
            {
                if (trash[t].CanDispose())
                {
                    trash[t].Dispose();
                    trash.RemoveAt(t);
                }
            }
            return(true);
        }

        // Sometimes we're not allowed to destroy GameObjects.
        // This could be because it's part of a prefab instance that is not currently being edited.
        // So instead of deleting this gameObject, we keep it around but disable it.
        // At the same time we keep track of it so we can recycle it when we can
        obj.Hide();
        @this.Trash.Add(obj);
        return(false);
    }