22

if you think there is a possibility of getting a null pointer exception, should you use an if statement to make sure the variable is not null, or should you just catch the exception?

I don't see any difference as you can put your logic to deal with the null pointer in the if statement, or in the catch block, so which one is best practise?

jgauffin
  • 99,844
  • 45
  • 235
  • 372
David Klempfner
  • 8,700
  • 20
  • 73
  • 153
  • 7
    check out http://stackoverflow.com/questions/1336094/using-try-catch-for-flow-control-net – argaz Jun 27 '13 at 05:35
  • 8
    exception is something that should not happen often, by definition. If null is a possibility by your flow, you should not let it trigger an exception. – Karthik T Jun 27 '13 at 05:36
  • 2
    catching exceptions is much slower than if .. else – Dmitry Bychenko Jun 27 '13 at 05:39
  • Its depend on if you catch general exception – Amit Jun 27 '13 at 05:41
  • Related: [When is it OK to use exception handling for business logic?](http://stackoverflow.com/q/5378005/486504) (and [my answer to that question](http://stackoverflow.com/a/5378142/486504) which, incidentally, along with the example in the question illustrates what makes exception handling difficult in cases like this). – user Jun 27 '13 at 08:51
  • 1
    The main problem is that when an `Exception` is thrown, it will (try to) obtain a stack trace, which will use up **a lot of time**. – Alvin Wong Jun 27 '13 at 10:11
  • relevant: http://blogs.msdn.com/b/ericlippert/archive/2008/09/10/vexing-exceptions.aspx – jk. Jun 27 '13 at 12:03

10 Answers10

36

I would say ALWAYS use logic to catch the exception, not try/catch.

Try/Catch should be used when you validate but some strange thing happens and something causes an error so you can handle it more gracefully.

logixologist
  • 3,694
  • 4
  • 28
  • 46
  • 7
    Just to add to this, I think the clue is in the name, an Exception that you catch is just that, an exception to the flow of your code that you could not predict or cannot handle. If logic can handle it its not an exception. – CeejeeB Jun 27 '13 at 11:31
20

There is no single answer that will suffice here, it depends.

Let's take a few scenarios so you can see what I mean.

Scenario: Method that takes a reference type parameter that does not accept null

You're defining a method, it takes a reference type parameter, say a stream object, and you don't want to accept null as a legal input parameter.

In this case, I would say that the contract is that null is not a valid input. If some code does in fact call that method with a null reference, the contract is broken.

This is an exception, more specifically, it's an ArgumentNullException.

Example:

public void Write(Stream stream)
{
    if (stream == null)
        throw new ArgumentNullException("stream");
    ...

I would definitely not just let the code execute until it tries to dereference the stream in this case, instead crashing with a NullReferenceException, because at that point I lost all ability to react when I know the cause.

Q. Why can't I return false instead of throwing an exception?

A. Because a return value is easy to silently ignore, do you really want your "Write" methods to just silently skip writing because you made a snafu in the calling code, passing the wrong stream object or something that cannot be written to? I wouldn't!

Scenario: Method returns a reference to an object, sometimes there is no object

In this case the contract is that null is a legal result. In my opinion, null is something to avoid because it is quite hard to make sure you handle correctly everywhere, but sometimes it is the best way.

In this case I would make sure to if my way around the result, to ensure I don't crash when the null reference comes back.

Generalisation

If you take a close look at the above two scenarios, you'll note one thing:

In both cases it comes down to what is being expected, what the contract is.

If the contract says "not null", throw an exception. Don't fall back to the old-style API way of returning false because an exceptional problem should not be silently ignored, and littering the code with if statements to ensure every method call succeeds does not make for readable code.

If the contract says "null is entirely possible", handle it with if statements.

Advertising

For getting a better grip on null problems, I would also urge you to get ReSharper for you and your team, but please note that this answer can be applied to any type of exception and error handling, the same principles applies.

With it comes attributes you can embed into your project(s) to flag these cases, and then ReSharper will highlight the code in question.

public void Write([NotNull] Stream stream)

[CanBeNull]
public SomeObject GetSomeObject()

To read more about the contract attributes that ReSharper uses, see

Lasse V. Karlsen
  • 380,855
  • 102
  • 628
  • 825
  • +1 for the excellent explanation by scenarios. And thx for the R# tip. That one was new to me. – Koen Jun 27 '13 at 06:58
  • See more information about the contract annotations available in ReSharper [here - introduction to resharper attribute contracts](http://blogs.jetbrains.com/dotnet/2010/11/resharper-nullreferenceexception-analysis-and-its-contracts/) and [here - additions to the contract attributes in ReSharper 7](http://blogs.jetbrains.com/dotnet/2012/08/contract-annotations-in-resharper-7/). – Lasse V. Karlsen Jun 27 '13 at 07:47
4

Well. Exceptions are just that. Exceptions. They are thrown when something unforseen has happened and should not be part of the normal program flow.

And that's what is happening here. You expected the argument to be specified when it's not. That is unexpected and you should therefore throw your own exception informing the user of that. If you want to get bonus points you can also include the reason to WHY the argument must be specified (if it's not obvious).

I've written a series of posts about exceptions: http://blog.gauffin.org/2013/04/what-is-exceptions/

jgauffin
  • 99,844
  • 45
  • 235
  • 372
  • 1
    this contradicts the post above by logixologist – David Klempfner Jun 27 '13 at 06:12
  • No. logixologist contradicts himself. First he says that he always use logic and then that try/catch can be used. If you read my article series you'll see that try/catch can seldom be used to rescue the situation. – jgauffin Jun 27 '13 at 06:27
  • The benefit to using logic to test for a null reference is you can throw a **meaningful** exception. `NullReferenceException` is the bane of my existence when debugging. The call stack tells you where to start, but doesn't tell you which of your 10 reference types are null. Wish we had the `variableName!` syntax for compiler supported "not nulls". But as a general rule, I leave exceptions to throw and I only use a `try-catch` if I can *handle* a potential exception. Like I said, however, null references might benefit from logic versus waiting for the exception as you can throw your own. – Adam Houldsworth Jun 27 '13 at 07:58
3

From a performance standpoint it really depends what you're doing. The performance impact from a try/catch block when no exception is thrown is minimal (and if you really need that last few percent of performance, you probably should rewrite that part of your code in C++ anyway). Throwing exceptions does have a major impact on simpler operations such as string manipulation; but once you get file/database operations in the loop they're so much slower that again it becomes a trivial penalty. Throwing across an App Domain will have a non-trivial impact on just about anything though.

Performance in Operations/second:

Mode/operation               Empty   String      File   Database    Complex
No exception            17,748,206  267,300     2,461   877         239
Catch without exception 15,415,757  261,456     2,476   871         236
Throw                      103,456   68,952     2,236   864         236
Rethrow original            53,481   41,889     2,324   852         230
Throw across AppDomain       3,073    2,942       930   574         160

Additional test results along with the source for the tests is available from the article Performance implications of Exceptions in .NET

0

I would rather suggest you use if-statement for NullReference exception. For other exception, try-catch should be good enough.

The reason I suggest if-statement for NullReference exception is because C# will not tell which variable is null. if that line has more than one object could be null, you will loss track. If you are using if-statement, you can have better logging to help you get the enough information.

NonStatic
  • 951
  • 1
  • 8
  • 27
0

The main Question is if it is a good idea to have methods returning Null at all, personally i do not have any problem with this, but as soon as you try to access modifiers of an object returned from this method and you forget to check if it is assigned this becomes an issue.

Ken has a good answer about this:

If you are always expecting to find a value then throw the exception if it is missing. The exception would mean that there was a problem.

If the value can be missing or present and both are valid for the application logic then return a null.

See this disscussion abou tthis issue:

Returning null is usually the best idea if you intend to indicate that no data is available.

An empty object implies data has been returned, whereas returning null clearly indicates that nothing has been returned.

Additionally, returning a null will result in a null exception if you attempt to access members in the object, which can be useful for highlighting buggy code - attempting to access a member of nothing makes no sense. Accessing members of an empty object will not fail meaning bugs can go undiscovered.

Some further reading:

Community
  • 1
  • 1
CloudyMarble
  • 36,908
  • 70
  • 97
  • 130
0

using try catch for the statements is not an good idea. because when you use try catch them it seems that if some error comes the code will not turninate the application. but if you are sure about what kind of error can come you can tap the error at that point. that will not produce any unknown errors. for example.

string name = null;

here i am going to use the name variable and i am sure that this will throw Null Refrance Error .

try
{
Console.writeLine("Name ={0}",name);
}
catch (NullRefranceException nex)
{
//handle the error 
}
catch(Exception ex)
{
 // handle error to prevent application being crashed. 
}

This is not a good practice while you can handle this kind of error and make your code more readable. like.

if(name !=null)
    Console.writeLine("Name ={0}",name);
JSJ
  • 5,653
  • 3
  • 25
  • 32
0

In my experience using if is better but only if you actually expect a null reference pointer. Without any bit of code or context its difficult to say when one option is better than the other.

There's also a matter of optimization - code in try-catch blocks won't be optimized.

Community
  • 1
  • 1
MBender
  • 5,395
  • 1
  • 42
  • 69
0

In general, try-catch blocks are great because they will break (move to the catch statement) whenever the exception occurs. If-else blocks rely on you predicting when the error will happen.

Also, catch blocks won't stop your code from halting when an error is hit.

-2

Its always better to use Try Catch other than if else Here Exceptions are two types namely handled and UN-handled exceptions Even if u want to handle some function when the Exception u can handle it...

Handled exception always allows you to write some implementations inside the Catch block Eg. An Alert Message, A new Function to handle when such exception occurs.

Ravi Chandran
  • 131
  • 2
  • 10
  • 3
    I disagree. Using Exceptions for catching nulls, getting invalid index of an array, division by zero, and other fairly common situations is in my opinion not a good idea. – Dariusz Jul 03 '13 at 08:08