Please, don't abuse try/catch

by Miha Markič 23. November 2006 15:06

You should have heard from experienced developers that you shouldn't abuse try/catch to handle a situation that is predictable and easily handled with an if statement. Even guys at [MS] preach this approach.

Take a look at this piece of code:

string fileName = "somefile.xml"; bool notFound; try { FileStream fs = File.Open(fileName, FileMode.Open); // do something } catch (FileNotFoundException) { notFound = true; }

While this method produces correct output (notFound=true) when file isn't found there are at least two problems in there:

  1. Method is slower when file isn't found (because of throwing exception overhead). This is just a small overhead.
  2. What's more annoying is that if you have Debugger/Exceptions... settings set to intercept all exceptions (shown in picture below) you will catch such exceptions even when there is nothing wrong with the code.

The reason why I am writting this post is that I get such an exception when creating an instance of IsolatedStorageFileStream class. Visual Studio correctly stopped on instance creation telling me that an exception of type FileNotFoundException occured.At first I was a bit puzzled why would I get FileNotFoundException when I was passing FileMode.Create flag. Doesn't make sense, right? Wrong. IsolatedStorageFileStream constructor internally implements similar (not same) code described above. It uses a handled exception for checking whether file exists even when using FileMode.Create!

Instead the code above could be rewritten as:

string fileName = "somefile.xml"; bool notFound; if (File.Exists(fileName) { FileStream fs = File.Open(fileName, FileMode.Open); // do something } else notFound = true;

This approach is more elegant, readable, faster and it doesn't throw anything on predictable problems. I guess [MS] guys could clean up a bit .net library.

UPDATE (gorazd pointed that there is a possibility that file disappears between File.Exists and File.Open - while I thought of this when I was writing this post I forgot to include it in the code). So, here is an improved v2:

string fileName = "somefile.xml"; bool notFound; if (File.Exists(fileName)) { try { FileStream fs = File.Open(fileName, FileMode.Open); // do something } catch (FileNotFoundException) { notFound = true; } } else notFound = true;

UPDATE: The good news is this behavior is a must only in Visual Studio 2003. Not because of a code change. No, there is actually an option to disable catching non-my-code exceptions. The option is turned on by default. So, here it is:

You'll find it in Tools/Options... Unfortunatelly that doesn't help if you are stuck in a Visual Studio 2003 world.

Tags:

.net

Comments (6) -

Laurent
Laurent
11/23/2006 7:34:05 PM #

I am heavily disturbed by dozens exceptions during ASP.NET 1.1 debugging sessions too.
The same way as you when you use IsolatedStorageFileStream ): !

Reply

Miha Markic
Miha Markic
11/23/2006 7:50:29 PM #

That sucks, doesn't it? Perhaps there could be an option such as "disable breaking on not my code".

Reply

gorazd
gorazd
11/23/2006 7:59:37 PM #

well, there is a chance that file is deleted between Exists and actually opening it...

Reply

Miha Markic
Miha Markic
11/23/2006 9:05:36 PM #

Hi gorazd,

Yep, that's the chance. In such case you should put both if and catch statements.

Reply

PetarR
PetarR
11/24/2006 5:35:37 AM #

"1. Method is slower when file isn't found (because of throwing exception overhead). This is just a small overhead."

I looked at ctor of IsolatedStorageFileStream in .NET 1.1 with Refactor. It results that try/catch in question is executed when "mode" parameter is FileMode.Append (Opens the file if it exists and seeks to the end of the file, or creates a new file).

Now, let us assume that this ctor with  FileMode.Append is called in majority of situations on existing files (seems logical because it is called Append and not Create).

I think that means that their implementation performs faster because in majority of cases it requires 1 IO operation (file open) and your implementation 2 (file exists + file open).

"Perhaps there could be an option such as disable breaking on not my code""

It exists something like that, but in .NET 2.0.
Look at DebuggerNonUserCodeAttribute Class.

Reply

Miha Markic
Miha Markic
11/24/2006 2:34:33 PM #

Hi Petar,

1. The speed difference isn't that important IMO.
2. I don't think DebuggerNonUserCodeAttribute can help in this scenario. And even if it helped you would have problems turning it on or off. Anyway, I updated my article.

Reply

Add comment

  Country flag

biuquote
  • Comment
  • Preview
Loading

Miha Markic

About me
Righthand
 
Microsoft MVP
 
Developer Express' DXSquad
INETA Country Leader for Slovenia
INETA Country Leader for Slovenia

Slovene Developer Users Group Lead
Friends of Red-Gate
LLBLGenPro Partner

Miha currently works as a free lance consultant and software developer specialized in .net area.
He graduated in Computer and information science at the University of Ljubljana, Slovenia. He has accumulated experience in various programming languages such as Java, Visual Basic 3-6 (MCP), Visual C++, Delphi, C# and VB.Net through years.
He has experience in practically all (technical) stages of project development, including planning, framework development, user interface, business processes, as well as testing and documenting. He has worked on big and small projects in Slovenia and abroad (e.g. participated in completing level 3 IS for the Nucor steel plant, Hertford, USA).
Currently he enjoys programming in .net environment using C#. Since 2000 he has been active in Developer Express' DX Squad and has been ECDL trainer and tester. He also gives lectures on conferences and other events in Slovenia.

Month List

Tag cloud

Most comments

Dan Dan
4 comments
ca Canada
Thomas Thomas
3 comments
de Germany
Sebastian Sebastian
1 comments
ca Canada

RecentComments

Comment RSS