Having Single and SingleOrDefault to throw a more succinct exception
May this solve the problem?
public virtual Fee GetFeeByPromoCode(string promoCode)
{
try
{
return _fees.SingleOrDefault(f =>
{
try
{
return f.IsPromoCodeValid(promoCode);
}
catch(InvalidOperationException)
{
throw new PromoCodeException();
}
});
}
catch (InvalidOperationException)
{
throw new TooManyFeesException();
}
}
I consider First() / Single() / SingleOrDefault() as a kind of Assert.
i.e. If you use them you don't want to catch the exception. Something is very wrong with your data and it should be handled as a critical error.
If multiple results is normal in your model, don't use exceptions to verify it.
From that perspective I don't think your Take(2) version is less obvious.