Даже проверки "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", и я действительно не знаю, действительно ли это может быть проблемой или нет.
Я понимаю смысл предупреждения, но что вы действительно можете сделать в этой ситуации, если вам действительно нужно проверить и исключить исключение в случае недействительности или пустоты?
Ответы
Ответ 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;
}