When calling Single or SingleOrDefault on an IEnumerable<T> and has more than one result, it throws an InvalidOperationException .
While the actual exception message is very descriptive, it's hard to write a catch that will only handle cases where calls to Single / SingleOrDefault fail.
public virtual Fee GetFeeByPromoCode(string promoCode) { try { return _fees.SingleOrDefault(f => f.IsPromoCodeValid(promoCode)); } catch (InvalidOperationException) { throw new TooManyFeesException(); } }
In this case, if IsPromoCodeValid also throws an InvalidOperationException , then it becomes ambiguous as to what catch is handling.
I could check the exception message, but I would like to avoid it, because I think it is dirty to process the code depending on the exception message.
My current alternative to SingleOrDefault as follows:
public virtual Fee GetFeeByPromoCode(string promoCode) { var fees = _fees.Where(f => f.IsPromoCodeValid(promoCode)).ToList(); if (fees.Count > 1) { throw new InvalidFeeSetupException(); } return fees.FirstOrDefault(); }
However, this code is much less obvious than the code above, and it also creates a less efficient query (if you use ORM with linq support) than using SingleOrDefault .
I could also do Take(2) with my second example to optimize it a bit, but this further confuses the purpose of the code.
Is there a way to do this without writing my own extension for both IEnumerable and IQueryable ?
source share