我只是花了一些時間撓了腦袋,當一個斷點似乎神奇地出現兩次在同一個地方,在一個枚舉。防止意外重新枚舉IEnumerable的技巧?
原來的錯誤是一個簡單的監督:
protected override void Extract()
{
LogGettingOffers();
var offerIds = CakeMarketingUtility.OfferIds(advertiserId);
LogExtractingClicks(offerIds);
foreach (var offerId in offerIds)
{
int rowCount;
var clicks = RetryUtility.Retry(3, 10000, new[] { typeof(Exception) },() =>
{
return CakeMarketingUtility.EnumerateClicks(dateRange, advertiserId, offerId);
});
foreach (var clickBatch in clicks.InBatches(1000))
{
LogExtractedClicks(offerId, clickBatch);
// SHOULD BE clickBatch, NOT clicks
Add(clicks);
}
}
End();
}
這使我想知道什麼(如果有的話),其中的一種可能需要編寫代碼捕獲這樣的錯誤的預防措施。
注意,我還不能肯定是有意義的走這條思路 - 也許答案是「不寫不正確的代碼」,這我很願意接受..
這裏的這產生的結果實際代碼:
public static IEnumerable<Click> EnumerateClicks(DateRange dateRange, int advertiserId, int offerId)
{
// initialize to start at the first row
int startAtRow = 1;
// hard code an upper limit for the max number of rows to be returned in one call
int rowLimitForOneCall = 5000;
bool done = false;
int total = 0;
while (!done)
{
Logger.Info("Extracted a total of {0} rows, checking for more, starting at row {1}..", total, startAtRow);
// prepare the request
var request = new ClicksRequest
{
start_date = dateRange.FromDate.ToString("MM/dd/yyyy"),
end_date = dateRange.ToDate.ToString("MM/dd/yyyy"),
advertiser_id = advertiserId,
offer_id = offerId,
row_limit = rowLimitForOneCall,
start_at_row = startAtRow
};
// create the client, call the service and check the response
var client = new ClicksClient();
var response = client.Clicks(request);
if (!response.Success)
{
throw new Exception("ClicksClient failed");
}
// update the running total
total += response.RowCount;
// return result
foreach (var click in response.Clicks)
yield return click;
// update stopping condition for loop
done = (response.RowCount < rowLimitForOneCall);
// increment start row for next iteration
startAtRow += rowLimitForOneCall;
}
Logger.Info("Extracted a total of {0}, done.", total);
}
說實話,我相信你的直覺是正確的:它只是不值得這個得太多。任何可能的選擇可能會更復雜。編寫更復雜的代碼以防止愚蠢的編碼錯誤感覺就像我的代碼味道。 –