Подтвердить что ты не робот

Даже проверки "IsNullOrEmpty" предоставляют предупреждения "Возможное множественное перечисление IEnumerable"

Теперь вопрос о SO о "возможных множественных перечислениях" , но этот вопрос более конкретный.

Пожалуйста, рассмотрите следующий метод, который принимает вход IEnumerable<string> как и выполняет данный метод по каждому из его элементов:

public static bool SomeMethod(IEnumerable<string> enumerable)
{
    if (enumerable.IsNullOrEmpty())
    {
        // throw exception.
    }
    else
    {
        return (enumerable.All(SomeBooleanMethod));
    }
}

В приведенном выше коде IsNullOrEmpty - это просто метод расширения, который запускает

return (!ReferenceEquals(enumerable, null) || enumerable.Any());

Проблема в том, что ReSharper предупреждает меня о "Возможных множественных перечислениях IEnumerable", и я действительно не знаю, действительно ли это может быть проблемой или нет.

Я понимаю смысл предупреждения, но что вы действительно можете сделать в этой ситуации, если вам действительно нужно проверить и исключить исключение в случае недействительности или пустоты?

4b9b3361

Ответ 1

Это означает, что вы (частично) итерации над IEnumerable более одного раза: сначала в вашем вызове Any() (которому нужно хотя бы инициализировать итерацию, чтобы увидеть, может ли перечислимый возвращать какие-либо элементы), и второй раз в All (который итерации начинается с начала).

Причина, по которой ReSharper предупреждает вас об этом, заключается в том, что перечисление по перечислимому может вызвать побочные эффекты, а непреднамеренное повторение дважды может вызвать побочные эффекты дважды, что может быть или не быть желательным.

Ответ 2

Как идентифицирует @tdammers, упомянутые "множественные перечисления" являются двумя перечислениями, требуемыми Any и All. Поскольку вы хотите отклонить пустую последовательность, лучшее, что я могу придумать, это:

public static bool SomeMethod(IEnumerable<string> enumerable)
{
    if (enumerable == null)
        throw new ArgumentNullException();

    // Manually perform an All, keeping track of if there are any elements
    bool anyElements = false;

    bool result = true;

    foreach (string item in enumerable)
    {
        anyElements = true;
        result = result && SomeBooleanMethod(item);

        // Can short-circuit here
        if (!result)
            break;
    }

    if (!anyElements)
        throw new ArgumentException();    // Empty sequence is invalid argument

    return result;
}