Checking a null parameter in C #

In C #, are there any good reasons (other than a better error message) for adding a null parameter value for each function where null is not a valid value? Obviously, the code that uses s still throws an exception. And such checks make the code slower and harder to maintain.

void f(SomeType s) { if (s == null) { throw new ArgumentNullException("s cannot be null."); } // Use s } 
+62
function null c #
Sep 28 2018-11-11T00:
source share
7 answers

Yes, there are good reasons:

  • It pinpoints what is null, which may not be obvious from a NullReferenceException
  • This causes the code to crash on invalid input, even if some other condition means the value is not dereferenced
  • This makes an exception before the method can have any other side effects that you might have reached before the first dereference
  • This means that you can be sure that if you pass the parameter to something else, you will not break their contract.
  • It documents your method requirements (using Code Contracts for this, of course, is even better)

Now about your objections:

  • This is slower: did you find that this is actually a bottleneck in your code, or do you guess? Profanity checks are very quick, and in the vast majority of cases they will not become a bottleneck.
  • This makes the code harder to maintain: I think the opposite. I think it’s easier to use the code where it made it clear whether the parameter can be zero, and where you are sure that this condition is met.

And for your statement:

Obviously, code that uses s will throw an exception anyway.

Really? Consider:

 void f(SomeType s) { // Use s Console.WriteLine("I've got a message of {0}", s); } 

This uses s but does not raise an exception. If it is not valid for s as null, and this indicates that something is wrong, an exception is the most appropriate behavior here.

Now that you put these argument validation checks, that's another matter. You can trust all the code in your class, so don't worry about private methods. You can trust the rest of your assembly so you don't have to worry about internal methods. You should almost certainly check the arguments for public methods.

Note: the one-parameter overload of the ArgumentNullException constructor should be just a parameter name, so your test should be:

 if (s == null) { throw new ArgumentNullException("s"); } 

Alternatively, you can create an extension method that allows some patience:

 s.ThrowIfNull("s"); 

In my version of the extension method (generic), I return the original value if it is not null, which allows me to write things like:

 this.name = name.ThrowIfNull("name"); 

You can also have an overload that does not accept the parameter name if you are not too worried about it.

+126
Sep 28 2018-11-11T00:
source share

I agree with John, but I would add one thing to this.

My attitude to when to add explicit null checks is based on these assumptions:

  • For your unit tests, there should be a way to implement every statement in the program. Operators
  • throw are operators.
  • The consequence of if is a statement.
  • Therefore, there must be a way to implement throw in if (x == null) throw whatever;

If there is no possible way for this statement, it cannot be tested and must be replaced by Debug.Assert(x != null); .

If there is a possible way to execute this statement, write a statement, and then write a unit test that uses it.

It is especially important that public methods of public types test their arguments in this way; you have no idea what a crazy thing your users will do. Give them "hey you skeleton, you are doing it wrong!" As soon as possible.

Private methods of private types, on the contrary, are much more likely in a situation where you control the arguments and can have a strong guarantee that the argument is never equal to zero; use the statement to document this invariant.

+44
Sep 28 '11 at 15:31
source share

Without an explicit if check, it can be very difficult to figure out what was null if you are not the owner of the code.

If you get a NullReferenceException from the depth inside the library without source code, you will probably have a lot of trouble figuring out what you did wrong.

These if checks will not make your code noticeably slower.




Note that the constructor parameter ArgumentNullException is the name of the parameter, not the message.
Your code should be

 if (s == null) throw new ArgumentNullException("s"); 

I wrote a code snippet to make this easier:

 <?xml version="1.0" encoding="utf-8" ?> <CodeSnippets xmlns="http://schemas.microsoft.com/VisualStudio/2005/CodeSnippet"> <CodeSnippet Format="1.0.0"> <Header> <Title>Check for null arguments</Title> <Shortcut>tna</Shortcut> <Description>Code snippet for throw new ArgumentNullException</Description> <Author>SLaks</Author> <SnippetTypes> <SnippetType>Expansion</SnippetType> <SnippetType>SurroundsWith</SnippetType> </SnippetTypes> </Header> <Snippet> <Declarations> <Literal> <ID>Parameter</ID> <ToolTip>Paremeter to check for null</ToolTip> <Default>value</Default> </Literal> </Declarations> <Code Language="csharp"><![CDATA[if ($Parameter$ == null) throw new ArgumentNullException("$Parameter$"); $end$]]> </Code> </Snippet> </CodeSnippet> </CodeSnippets> 
+6
Sep 28 2018-11-11T00:
source share

Maybe you should take a look at Code Contracts if you need a more convenient way to make sure that you don't get any null objects as a parameter.

+4
Sep 28 '11 at 15:39
source share

The main advantage is that you clearly define the requirements of your method from the very beginning. This makes it clear to other code developers that it really is a mistake for the caller to send a null value to your method.

Validation will also stop the method from executing before any other code is executed. This means that you don’t have to worry about making changes to a method that is left incomplete.

+2
Sep 28 2018-11-11T00:
source share

Saves some debugging when removing this exception.

The ArgumentNullException argument explicitly states that it was "s", which was null.

If you do not have this check and let the code work, you will get a NullReferenceException from some undefined string in this method. In the release, you will not get line numbers!

+2
Sep 28 2018-11-11T00:
source share

Original code:

 void f(SomeType s) { if (s == null) { throw new ArgumentNullException("s cannot be null."); } // Use s } 

Rewrite it as:

 void f(SomeType s) { if (s == null) throw new ArgumentNullException(nameof(s)); } 
-one
Nov 06 '17 at 18:39
source share



All Articles