Я столкнулся с странной проблемой, и мне интересно, что мне с этим делать.
У меня есть этот класс, который возвращает IEnumerable<MyClass>
, и это отложенное выполнение. Сейчас есть два возможных потребителя. Один из них сортирует результат.
См. следующий пример:
public class SomeClass
{
public IEnumerable<MyClass> GetMyStuff(Param givenParam)
{
double culmulativeSum = 0;
return myStuff.Where(...)
.OrderBy(...)
.TakeWhile( o =>
{
bool returnValue = culmulativeSum < givenParam.Maximum;
culmulativeSum += o.SomeNumericValue;
return returnValue;
};
}
}
Потребители вызывают отложенное выполнение только один раз, но если они будут называть его более того, результат будет неправильным, поскольку culmulativeSum
не будет reset. Я нашел проблему по ошибке при модульном тестировании.
Самый простой способ устранить проблему - просто добавить .ToArray()
и избавиться от отложенного исполнения за счет небольшого количества накладных расходов.
Я мог бы добавить unit test в класс потребителей, чтобы убедиться, что он вызывает его только один раз, но это не помешает новому пользователю, закодированному в будущем, из этой потенциальной проблемы.
Еще одна вещь, которая пришла мне в голову, заключалась в следующем: Что-то вроде
return myStuff.Where(...)
.OrderBy(...)
.TakeWhile(...)
.ThrowIfExecutedMoreThan(1);
Очевидно, этого не существует. Было бы хорошей идеей реализовать такую вещь и как бы вы это сделали?
В противном случае, если есть большой розовый слон, которого я не вижу, это будет оценено. (Я чувствую, что есть один, потому что этот вопрос касается очень простого сценария: |)
EDIT:
Вот пример использования плохих потребителей:
public class ConsumerClass
{
public void WhatEverMethod()
{
SomeClass some = new SomeClass();
var stuffs = some.GetMyStuff(param);
var nb = stuffs.Count(); //first deferred execution
var firstOne = stuff.First(); //second deferred execution with the culmulativeSum not reset
}
}