# V4003. Unity Engine. Avoid capturing variable in performance-sensitive context. This can lead to decreased performance.

Анализатор обнаружил захват переменной в лямбда-выражении внутри часто выполняемого метода. Захват переменных может приводить к снижению производительности из-за дополнительного выделения памяти.

Рассмотрим пример:

    void Update()
    {
      ....
      List<int> numbers = GetNumbers();
      int divisor = GetDivisor();
      var result = numbers.Select(x => x / divisor);
      ....
    }

Здесь 'Update' — метод Unity, выполняющий покадровое обновление. Метод 'Update' — часто вызываемый, и его не рекомендуется нагружать лишними операциями.

В приведенном примере используется лямбда-выражение с захватом переменной 'divisor'. Как упоминалось ранее, захват переменной из внешнего контекста приводит к дополнительному созданию объекта.

Таким образом, представленный участок кода создает дополнительную нагрузку на GC.

Оптимальная реализация метода может выглядеть следующим образом:

    void Update()
    {
      ....
      List<int> numbers = GetNumbers();
      int divisor = GetDivisor();

      var result = new List<int>(numbers.Count);
      for (int i = 0; i < numbers.Count; i++)
      {
        result.Add(numbers[i]/divisor);
      }
      ....
    }

Использование собственной реализации, аналогичной 'Select', позволяет избавиться от дополнительного выделения памяти и тем самым снизить нагрузку на GC.

Рассмотрим еще один пример:

    void Update()
    {
      ....
      List<int> numbers = GetNumbers();
      int divisor = GetDivisor();

      if (AreAllMultipleOf(numbers, divisor))
        ....
    }

    bool AreAllMultipleOf(List<int> lst, int divisor)
    {
      return lst.All(elem => elem % divisor == 0);
    }

Здесь из метода 'Update' вызывается метод 'AreAllMultipleOf', который определяет, являются ли все полученные числа кратными значению 'divisor'. Так же, как и ранее: 'Update' — часто вызываемый метод, выполняющий покадровое обновление в Unity.

В представленном случае метод 'AreAllMultipleOf' регулярно выполняется внутри 'Update', а значит, также является часто вызываемым.

Метод 'AreAllMultipleOf' для выполнения проверки использует лямбда-выражение с захватом переменных. Это приводит к дополнительному выделению памяти, которое может негативно сказаться на производительности приложения.

Оптимальная реализация может выглядеть следующим образом:

    void Update()
    {
      ....
      List<int> numbers = GetNumbers();
      int divisor = GetDivisor();

      if (AreAllMultipleOf(numbers, divisor))
        ....
    }

    bool AreAllMultipleOf(List<int> lst, int divisor)
    {
      foreach (int num in lst)
      {
        if (num % divisor != 0)
          return false;
      }
      return true;
    }

Здесь мы в очередной раз воспользовались собственной реализацией, что позволило избежать дополнительного выделения памяти и снизить нагрузку на сборщик мусора.