45

When writing code, how does one decide between using if/else or try/catch? For example, in checking for a file, should this be based on a method such as:

if (File.Exists("file.txt"))
{
    //do stuff
}

or a try/catch block?

Another example: writing to a file can be handled via an if/else block to create a file and then write to it, or a try/catch with an assumption that the file exists. What considerations are there in choosing?

jordanz
  • 367
  • 4
  • 12
blade113
  • 461
  • 1
  • 4
  • 4
  • This is a rather poor question as the two items serve completely different purposes in your code. It's like saying "Should I take my car or helicopter?" Depending on what you're trying to do, the answer changes. In the example given, both should still be used. – krillgar Jan 21 '16 at 20:15

15 Answers15

42

You should never use try/catch for flow control.

Generating an exception is an extremely expensive action. If/else is much faster and cleaner.

Zebi
  • 8,682
  • 1
  • 36
  • 42
  • 6
    opening a file is not only controlling the flow... exceptional things may happen. – L-Four May 31 '11 at 14:27
  • However when dealing with files you have to deal with different issues. You want, for example, to decide wether the action failed because the file was locked or because it simply doesn't exist. Furthermore you may be able to provide sensible defaults (i.e. create the file). – Zebi May 31 '11 at 15:46
  • 3
    Generating an exception may be expensive, but if you're pretty sure that the exception case will almost never happen, it turns out that if-else is actually a little bit slower. See my answer below, where I ran a test to see which one is faster if the exception / else case never happens. – Michael Zlatkovsky - Microsoft Jan 31 '12 at 17:45
  • 2
    Never say never. Try Catch to check if a file exists is much faster than File.Exists. In fact, the slowness of File.Exists increases much faster than the slowness of the Try Catch as folders become larger and larger. When checking if files exist on Window XP, try-catch can be magnitudes faster. Windows 7 behaves better with highly populated directories, and Win 8 is even better. But for XP, try catch is much better. – Vincent McNabb Dec 10 '12 at 01:07
  • Try/catch is, by default, a flow control statement. So, your first statement in the answer is void. Other than that, it is my personal opinion that if/else statements should be preferred when possible, despite the fact that c# is, by design, an exception driven error handling language. – ThunderGr Sep 30 '13 at 08:14
22

You should always use try/catch when you work with files, because the state of a file can change outside of your program.

Consider the following code bit:

if(File.Exists("file.txt"))
    File.Delete("file.txt")

The file might have been deleted by another process right after the if statement, before the Delete() call. When you try to delete it, an exception is raised.

When working with files there are also a lot more things to consider, that you might not be able to catch with ifs, for example the file is on a network connection that got unavailable, access rights that change, hard disk failure etc.

These things are outside the control of your program, so you should have exception handlers in place.

thumbmunkeys
  • 20,606
  • 8
  • 62
  • 110
  • 1
    To me this answer is not logical. java.io.File is certainly using if statements to determine whether or not to throw an exception. You could have very well tested a return value from delete to see if the file was successfully deleted. What I was expecting from an answer is if try catch blocks are more expensive than if else branching. – user13947194 Jan 02 '23 at 04:25
13

If you think the operation should normally succeed, then try/catch can be easier to read. Especially, if there are many reasons for failure (multiple catch blocks).

Otherwise, if it sometimes succeeds and sometimes fails - and does so for a specific reason, use if/else (this is known as structured exception handling).

Some people point out how exception handling with try/catch can be time consuming. I tend to read advice like that along the following lines: Don't do this in a tight inner loop, if your profiling indicates a performance problem. When coding your first draft, don't bother thinking about optimizing at this level at all!

Daren Thomas
  • 67,947
  • 40
  • 154
  • 200
  • 1
    +1. Also, isn't exception handling generally faster when the exception is _not_ being thrown? – Macke May 31 '11 at 10:54
  • @Macke: I'm pretty sure it is fast and only gets slow when you have to unwind the exception stack, *but* I wouldn't bet on it being faster than a condition. I never did bother to look up how this is done. Maybe we should all go study some compiler/interpreter source and come back when we're done? – Daren Thomas May 31 '11 at 13:31
8

Just to put the topic to rest (yes, the question was posed 8 months ago, but the internet always knows!), I decided to run a little test for which is more efficient if you're pretty sure you won't have an exception -- e.g., the "else" part is going to only happen 0.001% of the time. As it turns out, if you never have to catch/else anything, the try-catch is about 4% faster (on my machine, anyway). Here's the code and the accompanying results:

CASE 1: if-else:

var startTime = DateTime.Now;
int bazillion = 100000000;
int[] list = {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20};
for (int i = 0; i < bazillion; i++)
{
    for (int k = 0; k < list.Length; k++)
    {
        if (k >= 0)
        {
            list[k] = i;
        }
        else
        {
            // do nothing.
        }
    }
}
var executionTime = DateTime.Now - startTime;
Debug.WriteLine (executionTime.TotalMilliseconds);

Execution times (milliseconds) on 5 runs: 7441.4256, 7392.4228, 7545.4316, 7531.4308, 7323.4188.
Average = 7446.82592 milliseconds


CASE 2: try-catch:

var startTime = DateTime.Now;
int bazillion = 100000000;
int[] list = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20 };
for (int i = 0; i < bazillion; i++)
{
    for (int k = 0; k < list.Length; k++)
    {
        try
        {
            list[k] = i;
        }
        catch (Exception e)
        {
            // do nothing
        }
    }
}
var executionTime = DateTime.Now - startTime;
Debug.WriteLine(executionTime.TotalMilliseconds);

Execution times (milliseconds) on 5 runs: 7258.4152, 7137.4083, 7070.4044, 7052.4033, 7120.4073 Average = 7127.8077 milliseconds


Conclusion (based on this rather simplistic example; actual mileage may vary, etc):
In terms of sheer numbers, if you're pretty dang sure that the exception/else case will not occur, try-catch is about 4% faster than having to execute the "if" clause every single time.

  • Of course, if you **do** expect exceptions to happen, I fully agree with the other responses that handling it via if-else (at least the preliminary file-existing check) is more efficient. Here's one article I stumbled on that highlights just **how** significant the difference can be: [http://www.dotnetexpertguide.com/2011/12/efficiencies-use-of-try-catch-block.html](http://www.dotnetexpertguide.com/2011/12/efficiencies-use-of-try-catch-block.html) – Michael Zlatkovsky - Microsoft Jan 31 '12 at 17:48
  • In addition to what you say, this kind of profiling results depend on whether this test was done on a debug or release version of the code. Code optimization makes if statements much faster. – ThunderGr Sep 30 '13 at 08:02
  • I also ran a test similar to Michael's. I did the test on a Release build. I got comparable results. But I went a step further by including a test try/catch Failure to see how long a catch costs. It is literally 1000x slower to catch an exception than to simply hit an Else statement. – JamesHoux Apr 02 '18 at 15:02
6

Just a thought... one of the answers was that you should do a try catch if, for example, you have division by zero possibility. I wonder why? You are in control here, you can check before you divide, and act upon. If it's zero, you just don't need to do the division, but instead execute another logic.

I would only use try catch in the case that you are not in control or cannot (or doesn't make sense) check things beforehand (opening a file,...).

In your case, I would use File.Exists and try/catch. File.Exists as a business check (no need to open it when it doesn't exist), try/catch to catch any exceptions that may occur while opening the file.

L-Four
  • 13,345
  • 9
  • 65
  • 109
5

in general it depends

For file based stuff you almost always want to try the operation and handle failures rather than check first. the reason being that the file system is a shared resource and you cannot guarantee that after file.exists returns true the file does exist as some other process may have deleted it in the mean time.

jk.
  • 13,817
  • 5
  • 37
  • 50
5

You use try/catch when something unexpected ( an exception ) might happen and you want to do something special about it, like :

try
{
   //Do something that might rise an exception, say a division by 0
   //this is just an easy example as you might want to check if said value is not 0
   //before dividing
   int result = someNumberOfMine / anUnsafeNumber;
}
catch
{
   //if something unexpected happened, do a special treament
}

In your particular case, I would recommand using File.Exists to verify the presence of the file instead of using a try/catch block since the presence or not of the file can be checked before doing anything with it.

Smoothcity
  • 171
  • 5
4

Exceptional handling should only be done or used in exceptional cases.

In a scenario which depends on whether a File exists or not it doesn't make sense to use try catch block when simply you can do

if(File.Exists(path))
{
}
else
{

}

Exceptional handling cause a lot of performance hit so try to minimize the exceptional cases by applying more check in your code like if File.Exists(path))

Haris Hasan
  • 29,856
  • 10
  • 92
  • 122
  • 2
    I wouldn't feel safe here. I guess there are situations where the file exists but you cannot open it due to being in use or someting? – L-Four May 31 '11 at 11:54
4

As some answers have already pointed out, it depends.

If/else are used for flow control, but so can Exceptions with the added plus of catching a error that occurs. But as Turowicz pointed out it's considered bad practice to a lot of people, to use try/catch more than the Minimum of what you have to.

You can always read these articles from Ned Batchelder (Talks about return codes, as a alternative to using exceptions) and Joel Spolsky (Why he doesn't like programming with exceptions) to get a idea of what other think of exceptions and then make your own mind up.

Johann du Toit
  • 2,609
  • 2
  • 16
  • 31
  • 1
    Very good links! To quote a part of one of the comments there(by Ray Trend): "There typically are 10 kinds of people, those who think in binary and those who don't... oops, throw XInappropriateMetaphor". Contrary to C++, where there is a choice, in C# we are obliged to work with exceptions. Both methods have advantages and disadvantages. For one more time, tools are only tools. Their effectiveness depend on the user... – ThunderGr Sep 30 '13 at 08:33
2

When the file is expected to not exist, check for existence first. But when the missing file is a unusual state you should indicate this exceptional state with an exception.

So the basic idea is: Try to avoid exceptions on expectable circumstances.

PVitt
  • 11,500
  • 5
  • 51
  • 85
2

Generally you should do both. try/catch to avoid exceptional situations (file was suddenly deleted from another thread). And if/else to handle non-exceptional (check if file exists). Try/catch is relatively slower than a usual if/else so it does not worth to use it for everything.

Oleg
  • 798
  • 3
  • 7
2

The adage "Exceptions should be exceptional" is useful when making these kinds of decisions. The principal being that you should handle known situations with standard program flow (i.e. if statements) so that exceptions represent unexpected situations (i.e. bugs).

Of course, like any rule, it's there to be broken.

Also, I wouldn't get too worried about the performance impact of exception handling. The overhead is pretty much negligible in all but extreme situations.

Andy Holt
  • 572
  • 2
  • 9
2

When you can already handle a situation before executing it, you should use if-else. But in situations where you can't know if something is going to work or not until you actually do it, use try-catch.

Case 1: Valid use of Try-Catch

boolean isNumber(String input) {
    try {
        Integer.parseInt(input);
        return true;
    } catch (NumberFormatException) {
        return false;
    }
}

You can't know if input is a number until you actually "try" to parse it. Hence, use try-catch.

Case 2: Valid use of if-else

boolean isNotNull(Object o) {
    if (o != null) {
        return true;
    } else {
        return false;
    }
}

I can know an object is null before calling a method on it. Hence, use if-else.

Case 3: Invalid use of try-catch when if-else could have sufficed

boolean isNotNull(Object o) {
    try {
        // Some operation of object to know it's not null
        o.hashCode();
        return true;
    } catch (NullPointerException e) {
        return false;
    }
}

Tip: Use if-else as a guard for your application, like checking null values, handle edge cases, etc. For defining different application flows, use polymorphism to have better state management.

1

As it is obvious from all the answers, there is no standard/approved way to decide whether you should use one or the other. If done correctly, both methods will be effective. If done incorrectly, both methods will be inefficient.

I prefer if/else statements when it is meaningful(i.e. inside my own functions) and Try blocks when I call functions I have no control over.

In the above example, File.Exists() would be sufficient if you control the file(meaning no other program is likely to manipulate it) but not sufficient if there is a possibility that the file will be gone between checking and using.

File operations, in general, are better handled with exceptions in most cases, in my experience, because these very file operations, in c#, are raising exceptions. They do not return error codes that could be checked with if statements.

ThunderGr
  • 2,297
  • 29
  • 20
0

For this you know the file exit problem. So you prefer if else.

If you don't know the problem, better to use try catch.

i suggest the both, like below

try 
{
  if(File.Exists(path)) 
  { 
     do work
  } 
  else 
  {
     messagebox.show("File Path Not Exit");
  } 
}
catch(Exception e) 
{
 messagebox.show(e); 
}

it catch all the errors, which we not think.

Sagotharan
  • 2,586
  • 16
  • 73
  • 117
  • 1
    +1 for fail-safe code, but the example is redundant. The if statement does exactly what the try/catch does, only to one specific instance. MessageBox.Show(e.Message) will return the message "File does not exist", anyway. I would suggest rewriting it with something meaningful. – ThunderGr Sep 30 '13 at 08:08