Иногда я использую конструкции LINQ в своем источнике С#. Я использую VS 2010 с ReSharper. Теперь я получаю предупреждение "Возможное множественное перечисление IEnumerable" от ReSharper.
Я бы хотел реорганизовать его в соответствии с лучшими практиками. Вот кратко, что он делает:
IEnumerable<String> codesMatching = from c in codes where conditions select c;
String theCode = null;
if (codesMatching.Any())
{
theCode = codesMatching.First();
}
if ((theCode == null) || (codesMatching.Count() != 1))
{
throw new Exception("Matching code either not found or is not unique.");
}
// OK - do something with theCode.
Вопрос. Должен ли я сначала сохранить результат выражения LINQ в списке? (Я уверен, что он не вернется больше, чем несколько строк - скажем, максимум 10).
Любые намеки оценили.
Спасибо, Павел
Да, вам нужно сохранить результат как List\Array, а затем использовать его. В этом случае он не будет перечислять его пару раз.
В вашем случае, если вам нужно быть уверенным, что есть только один элемент, удовлетворяющий условию, вы можете использовать Single
- если будет более одного элемента, удовлетворяющего условиям, он будет генерировать исключение. Если вообще не будет предметов, это тоже исключение.
И ваш код будет проще:
string theCode = (from c in codes where conditions select c).Single();
Но в этом случае вы не можете изменить текст исключения, или вам нужно обернуть его в собственный блок try\catch и перестроить его с помощью настраиваемого текста \exception
Поскольку вы хотите проверить, является ли ваше условие уникальным, вы можете попробовать это (и да, вы должны сохранить результат):
var codes = (from c in codes where conditions select c).Take(2).ToArray();
if (codes.Length != 1)
{
throw new Exception("Matching code either not found or is not unique.");
}
var code = codes[0];
Take(2)
?
Финализация, перечислимая с помощью .ToList()
/.ToArray()
, избавится от предупреждения, но для того, чтобы понять, лучше ли это, чем несколько перечислений или нет, будет зависеть от реализации codes
и conditions
. .Any()
и .First()
являются ленивыми примитивами и не будут выполняться за первым элементом, а .Count()
может вообще не пострадать, поэтому преобразование в список может оказаться более расточительным, чем получение нового счетчика.
null
,Single
не сгенерирует исключение, но код OP сработает. Обычно это не проблема, но стоит отметить, что это не обязательно замена.