You don't check for StartDate > EndDate:
This is not caught:
Auction auction = new Auction("AAA", new DateTime(2019, 3, 2), new DateTime(2019, 3, 1)); public int CurrentHighestBid
{ get { return bids.Max(c => (int?)c.Value) ?? 0; } } Instead of return bids.Max(c => (int?)c.Value) ?? 0;, you can write return bids.Max(c => (int?)c.Value).GetValueOrDefault();. But why do you cast to int?
In ValidateBid(double value, User user) you check the start date but you don't check the end date.
In
public void RemoveBid(double value, User user) { var bid = bids.Where(c => c.Value == value).FirstOrDefault(); if (bid != null) bids.Remove(bid); } you're not using the user argument to anything. I would expect the condition to be something like (you can skip the Where-call):
var bid = bids.FirstOrDefault(b => b.Value == value && b.User == user); Futher: Remove(...) returns a boolean value to indicate if something was removed or not. You could return that value from RemoveBid() to let the client know...:
public bool RemoveBid(double value, User user) { var bid = bids.Where(c => c.Value == value).FirstOrDefault(); if (bid != null) return bids.Remove(bid); return false; } According to the use of exceptions and validation of input, I think you have to distinguish between input/states that hinders a normal or valid execution of the program, for instance a null reference or a StartDate > EndDate, and voilationviolations of business rules that doesn'tdon't cause the program to stop working, but make invalid or unwanted results - like value < ReservePrice. The first type should be thrown as exceptions while the latter should be handled with useful return values and/or messages. Ideally seen.
But it can be difficult to determine the difference (for instance: is StartDate > EndDate a business rule or an exception?), so it is often seen, that exceptions is used in both cases. What ever you choose do it consistently and document which exceptions are thrown where and why. Never fail to throw an exception, just because you feel you have too many :-). If you think you have to throw too many exception, you should maybe consider if the overall design is right.