c# - Technique to prevent accidental re-enumeration of IEnumerable? -
i spent time scratching head when breakpoint seemed magically appear twice in same spot, inside enumerator.
it turned out bug straight forward oversight:
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 clickbatch, not clicks add(clicks); } } end(); }
this leads me wonder (if any) kind of preventative measures 1 might take write code catches error this.
note, i'm not positive makes sense go down line of thought - maybe answer "don't write incorrect code", i'm willing accept..
here's actual code yields results:
public static ienumerable<click> enumerateclicks(daterange daterange, int advertiserid, int offerid) { // initialize start @ first row int startatrow = 1; // hard code upper limit max number of rows returned in 1 call int rowlimitforonecall = 5000; bool done = false; int total = 0; while (!done) { logger.info("extracted total of {0} rows, checking more, starting @ row {1}..", total, startatrow); // prepare 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 client, call service , check response var client = new clicksclient(); var response = client.clicks(request); if (!response.success) { throw new exception("clicksclient failed"); } // update running total total += response.rowcount; // return result foreach (var click in response.clicks) yield return click; // update stopping condition loop done = (response.rowcount < rowlimitforonecall); // increment start row next iteration startatrow += rowlimitforonecall; } logger.info("extracted total of {0}, done.", total); }
for specific issue, i'd solution "don't write incorrect code". when results can generated without altering state (like when enumerate elements list), think should okay create multiple enumerators enumerable.
you create ienumerable
wrapper ensure getenumerator
called once, if legitimately need call twice? want catch mistakes, not catch enumerables being enumerated multiple times, , that's not can put in software solution.
maybe issue clickbatch
, clicks
have same type, compiler couldn't distinguish between either.
Comments
Post a Comment