21

I have a class:

class Foo
{
    public Foo(string bar)
    {
        if (string.IsNullOrEmpty(bar))
            throw new Exception("bar must not be null or empty.");
    }
}

What is the most correct exception type to throw?

Viable candidates are:

  1. ArgumentNullException
  2. ArgumentException
  3. InvalidOperationException
  4. TypeInitializationException (not this as per dasblinkenlight below)

My instinct is to go with InvalidOperationException, as the caller is attempting to construct the object in a illegal state, though ArgumentException has merits as well.

I wish there was a StringNullOrEmptyException, wouldn't that be great?

Edit Thanks for the suggested question, it is similar, but I was asking specifically about it happening in the constructor and whether that would change the recommendation at all.

BanksySan
  • 27,362
  • 33
  • 117
  • 216
  • What makes you think TypeInitializationException would be adequate here? – Thomas Levesque Nov 22 '13 at 21:09
  • 1
    BTW, if you want a StringNullOrEmptyException, you can go ahead and create it ;) – Thomas Levesque Nov 22 '13 at 21:09
  • 1
    I know I could make one, but I don't want to. – BanksySan Nov 22 '13 at 21:12
  • @ThomasLevesque My thinking was as `The exception that is thrown as a wrapper around the exception thrown by the class initializer` that it was *sort of* initializing (I know initializers are not this bit I wanted to note all the candidates.) – BanksySan Nov 22 '13 at 21:14
  • I like the answer in [this older question](http://stackoverflow.com/questions/2480521/argumentexception-or-argumentnullexception-for-string-parameters). –  Nov 22 '13 at 21:16
  • @hvd I considered an extension method as well... Could well be the neatest solution... Really though, if I were doing that then I think I'd prefer a "Should not be null or empty" exception. – BanksySan Nov 22 '13 at 21:17

3 Answers3

20

I suppose the most correct implementation would be this:

if (bar == null) { throw new ArgumentNullException (...); }
else if (bar.Trim() == "") { throw new ArgumentException (...); }

but we might be straining a gnat and swallowing a camel. It's probably not terribly important.

On the other hand, you could build the StringNullOrEmptyException class.

Mike Perrenoud
  • 66,820
  • 29
  • 157
  • 232
  • 3
    I agree it might be a *tad* overly pedantic, but it is niggling at me. Knowing me, it will continue to do so for a few days (**cough** weeks) – BanksySan Nov 22 '13 at 21:11
  • For future reference, the latest implementation of .NET provides a static method to do exactly this: ArgumentException.ThrowIfNullOrEmpty https://learn.microsoft.com/en-us/dotnet/api/system.argumentexception.throwifnullorempty?view=net-7.0 – Mathieu Aug 18 '23 at 09:09
15

One very common way of handling situations like this is to throw two different exceptions - one for the null, and another one for the invalid non-null string:

if (bar == null) {
    throw new ArgumentNullException("bar");
}
if (string.IsNullOrWhiteSpace(bar)) {
    throw new ArgumentException("bar");
}

Since you mentioned other exceptions, here is what they signify:

  1. ArgumentNullException - Indicates that the argument in question is null
  2. ArgumentException - Indicates that the argument in question is not null, but is otherwise invalid.
  3. InvalidOperationException - Indicates that the operation cannot be performed in the current state of the object.
  4. TypeInitializationException - Indicates that the type (not an instance of the type, but the type itself) cannot be initialized.

The first three exceptions from this list always indicate a programming problem on the side of the caller, i.e. callers receiving them know that they must fix their code, because they are calling your API incorrectly.

The last exception indicates a programming problem on your side, i.e. the callers receiving this error know that they must call you to fix your error, or reconfigure the way in which they installed your library.

Sergey Kalinichenko
  • 714,442
  • 84
  • 1,110
  • 1,523
  • Good point on 4! 3 would be perfect, except that the object technically doesn't exist yet, but the caller is attempting to put it in an illegal state. – BanksySan Nov 22 '13 at 21:16
  • 1
    @BanksySan `ArgumentException` and its subclass `ArgumentNullException` are designed for situations when objects do not exist. – Sergey Kalinichenko Nov 22 '13 at 21:19
  • The mentioned meaning on `ArgumentException` is incorrect, the class descriptions states "The exception that is thrown when one of the arguments provided to a method is not valid.". `ArgumentNullException` is a specific subcase of `ArgumentException`. – Imre Pühvel Jan 04 '19 at 10:20
10

ArgumentException makes the most sense here for the following reasons

  • ArgumentNullException -> not valid because the string could be empty
  • InvalidOperationException -> it is not an operation that is failing, it is an argument in a constructor

If you really really want a StringNullOrEmptyException, you can create it yourself but most tend to agree that one should stick to the system defined Exceptions

David Pilkington
  • 13,528
  • 3
  • 41
  • 73
  • Why should one shy away from custom Exceptions? Just due to their innate lack of documentation and "familiarity" to other developers who might work on or inherit the application? – sab669 Nov 22 '13 at 21:12
  • Maintainability is usually the main issue. Documentation is one of the few skills that developers actually work on so it is often left to the end or even forgotten – David Pilkington Nov 22 '13 at 21:15