>
>
>
V3191. Iteration through collection mak…


V3191. Iteration through collection makes no sense because it is always empty.

Анализатор обнаружил попытку обхода пустой коллекции. Такая операция не имеет смысла: скорее всего, код содержит ошибку.

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

private List<Action> _actions;
....
public void Execute()
{
  var remove = new List<Action>();
  foreach (var action in _actions)
  {
    try
    {
      action.Invoke();
    }
    catch (Exception ex)
    {
      Logger.LogError(string.Format("Error invoking action:\n{0}", ex));
    }
  }
  foreach (var action in remove)
    _actions.Remove(action);
}

Метод 'Execute' поочередно вызывает делегаты из списка '_actions', а также ловит и логирует возникающие в процессе выполнения ошибки. Помимо основного цикла, в конце метода есть еще один, который должен удалять из списка '_actions' делегаты, хранящиеся в коллекции 'remove'.

Проблема здесь в том, что коллекция 'remove' всегда будет пустой. Она создается в самом начале метода, но не заполняется в процессе. Таким образом, последний цикл никогда не будет выполнен.

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

public void Execute()
{
  var remove = new List<Action>();
  foreach (var action in _actions)
  {
    try
    {
      action.Invoke();
    }
    catch (Exception ex)
    {
      Logger.LogError(string.Format("Error invoking action:\n{0}", ex));
      remove.Add(action);
    }
  }
  foreach (var action in remove)
    _actions.Remove(action);
}

Теперь добавляем в коллекцию 'remove' делегаты, при исполнении которых возникли исключения, чтобы впоследствии удалить их.

Анализатор также может выдать предупреждение на вызов метода, выполняющего обход коллекции.

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

int ProcessValues(int[][] valuesCollection,
                  out List<int> extremums)
{
  extremums = new List<int>();

  foreach (var values in valuesCollection)
  {
    SetStateAccordingToValues(values);
  }
  return extremums.Sum();
}

Метод 'ProcessValues' принимает массивы чисел для обработки. В данном случае нас интересует коллекция 'extremums': она создается пустой и не заполняется в процессе выполнения метода. При этом 'ProcessValues' возвращает результат вызова метода 'Sum' на коллекции 'extremums'. Код выглядит ошибочным, так как вызов 'Sum' всегда возвращает 0.

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

int ProcessValues(int[][] valuesCollection,
                  out List<int> extremums)
{
  extremums = new List<int>();

  foreach (var values in valuesCollection)
  {
    SetStateAccordingToValues(values);
    extremums.Add(values.Max());
  }
  return extremums.Sum();
}