Lets have an imaginary function:
void Dream(string theme, int rating) {
if (theme == null) { throw new ArgumentNullException(theme, "Theme must not be null."); }
if (rating < 0) { throw new ArgumentOutOfRangeException(theme, "Theme must not be null."); }
if (!OtherCheck(theme, rating)) { throw new ArgumentException(theme, "Some other reason."); }
...
}
On first look it looks fine. As always, devil is in the details. Let’s see how constructors for these functions look like:
public ArgumentNullException (string paramName, string message)
public ArgumentOutOfRangeException(string paramName, string message)
public ArgumentException (string message, string paramName)
Notice small difference in last line? Yes, order of arguments is different. Once this code is written you will probably never notice it unless you have code analysis turned on (CA2208). Unit tests will still catch correct exception and 95% developers will probably just skip over it because it “looks right”.
Would this be a critical bug? Well, not really. All properly written exception handling code will still work. Worst thing that might happen is for user to see wrong exception text. Chances are that this will be one of bugs that sits for ages although it is trivial to fix.
It is pointless to discuss whether ArgumentException
has a bug in parameter ordering. Even if it is a bug (and I personally think it is), it will never get fixed. Fixing it would mean that you automatically break code for someone else and I cannot imagine any sensible person approving of this. Best that you can do is to just forget this class exists. ArgumentOutOfRangeException
fits most of use cases for it anyhow.
PS: Everybody would probably be happier if ArgumentException was an abstract class.
PPS: Don’t let me get started ranting about ArgumentNullException
and why it was wrong to have three argument exceptions in framework.