7

I was reading this post where the answerer mentioned he prefered ArgumentNullException over NullReferenceException.

MSDN mention that for NullReferenceException:

The exception that is thrown when there is an attempt to dereference a null object reference.

On ArgumentNullException they say:

The exception that is thrown when a null reference (Nothing in Visual Basic) is passed to a method that does not accept it as a valid argument.

The answerer seems to say that you can use either.

Is there any reason or any case where I should choose one over the other?

P.S.

I know this question could be opinion based. I want fact, context and situation. I am not interested by personnal preference.

Massimiliano Kraus
  • 3,638
  • 5
  • 27
  • 47
Chax
  • 1,041
  • 2
  • 14
  • 36
  • 1
    *I should choose one over the other* Do you mean which should you throw, or which should you let happen? – DaveShaw Sep 15 '16 at 20:59
  • 1
    Very similar question to http://stackoverflow.com/questions/463302/argumentnullexception-or-nullreferenceexception-from-extension-method whose answers are pertinent to this question. – hatchet - done with SOverflow Sep 15 '16 at 21:05
  • 1
    You cannot use either. NRE must be reserved for programs that *actually* died from dereferencing null. You use ArgumentNullException to *prevent* them from falling over on NRE. Tells the client programmer "I *know* you are doing it wrong, never pass null please". NRE sends no such exquisite message, when it is thrown then you cannot be sure that it is your bug or the library's bug. – Hans Passant Sep 15 '16 at 21:13
  • @DaveShaw Which i should throw, my question was broad :S – Chax Sep 15 '16 at 21:44

3 Answers3

19

If you are explicitly throwing the exception in your code, you should choose ArgumentNullException.

NullReferenceException is thrown automatically by the CLR when a null reference / pointer is dereferenced:

unsafe
{
    int* ptr = null; // Null pointer.
    int val = *ptr; // NullReferenceException thrown.
}

This most commonly happens when method or property is called on a null reference:

string text = null;
string substring = text.Substring(0, 2); // NullReferenceException thrown.

In most cases, NullReferenceException should not be explicitly thrown in code.

ArgumentNullException is used to check for cases when a null reference is passed as a parameter, usually to prevent a NullReferenceException.

static string FirstTwo(string value)
{
    if (value == null)
    {
        throw new ArgumentNullException(nameof(value));
    }
    return value.Substring(0, 2); // without the original check, this line would throw a NullReferenceException if value were null.
}

The purpose of this check is to clearly let the caller know that null was passed and null is not allowed. Otherwise, if you simply let the NullReferenceException be thrown, the caller would only see

Object reference not set to an instance of an object

which is not as meaningful as this (when using the check):

Value cannot be null. Parameter name: value

Mr Anderson
  • 2,200
  • 13
  • 23
4

NullReferenceException is never thrown intentionally by convention. It signals an unintentional precodition violation. Therefore, it almost always signals a bug. The bug is in the code that throws the exception.

All NullReferenceExceptions should be considered bugs by convention. 99% of them are true bugs. 1% are not true bugs but it's worth the time time to prevent them and throw a more meaningful exception type to uphold the convention.

Use Argument*Exception to signal that you reject the argument that was passed. NullReferenceException means that the programmer of the code that throws this exception has made an error.

Treat NullReferenceException as a failing assertion that was provided by the runtime. Argument*Exception means "I thought about this case and I consciously reject it.".

usr
  • 168,620
  • 35
  • 240
  • 369
1

Even framework extension methods that look like they would throw a NullReferenceException, instead throw ArgumentNullExceptions:

List<string> list = null;
var results = list.Select(x => x); //ArgumentNullException

From just looking at the code (and without prior knowledge that Select is an extension method) this should throw a NullReferenceException... if the framework doesn't even throw them in this situation, I would always stick to using ArgumentNullException

Scott Perham
  • 2,410
  • 1
  • 10
  • 20