1

Usually, when I work with files and directories and I want to check that a path of a a directory or a file exists, I just use something like that:

if (Directory.Exists(path))
{
     //Something...
}

However, if I understood this answer correctly, it is recommended to allow the exception still be thrown, meaning that rather than using if, use try.. catch.

Is that a general approach when working with files and directories or there are times that it is preferable using if(Directory.Exists... or something of that sort?

NOTE: After seeing the first responses, just wanted to clarify that the cases when certain directory/path might not exist is an expected and normal behavior.

Community
  • 1
  • 1
Eugene S
  • 6,709
  • 8
  • 57
  • 91
  • Normally, you wouldn't want an exception to be part of your normal flow of execution. For example, you wouldn't want to assume a directory exists by passing its path to `DirectoryInfo`, catching an exception an then creating it when it throws a directory not found exception. – Yuval Itzchakov Feb 17 '15 at 06:31
  • IMHO, exceptions are costly and there is nothing wrong in validating a data for its correctness by code. [ Eg. you can still divide a number with 0 and capture it with exception, but I feel doing a sanity check on the data is much better]. Experts on SO can comment more.. – Thangadurai Feb 17 '15 at 06:34
  • You always have to assume that IO might cause an exception. Just because the directory existed a few milliseconds earlier doesn't mean it still exists now. It's unlikely, but possible. – Dirk Feb 17 '15 at 07:01

2 Answers2

2

You nearly always have to catch exceptions, especially for I/O errors, somewhere, lest the program simply be killed when one occurs.

In many scenarios, it makes sense to also first check for valid input (e.g. Directory.Exists()). This allows you to efficiently and in a user-friendly way report and respond to obvious user-error scenarios.

But you have no guarantee that the directory won't be deleted between the time you execute that call and the time you try to access it in some way. Or that if the directory is on a remote share, the network won't fail. Or that you won't have some other kind of I/O error.

There are a few exceptions that just aren't worth catching. Unexpected OutOfMemoryException for example (as opposed to some data structure simply getting too large), or other types of internal .NET failures. The likelihood of recovering from those types of errors is minimal. But for anything else, you at some point should be catching exceptions that could happen. Sometimes this simply means a top-level catch (Exception e), where you will log the exception in some way before exiting the program cleanly.

(I will note that exceptions that are uncaught and which cause the application to be terminated will generally get logged in the system event log. So as long as users are comfortable inspecting the log and retrieving exception information from there, then there's no need to catch all exceptions…just those you know what to do with).

Peter Duniho
  • 68,759
  • 7
  • 102
  • 136
  • Thanks for your answer. So, you reckon, I still should use `try .. catch` mechanism, even if existing and non-existing files/directories are all part of normal, expected scenario? – Eugene S Feb 17 '15 at 07:09
  • @EugeneS: Yes, definitely. Especially in I/O scenarios where the execution of your code depends on external components that you can't guarantee will always operate successfully, you need to use `try`/`catch`. Definitely _do_ also include explicit checks for non-existent files or directories, especially if that's a valid scenario, but even if it could be an error, to make the user experience nicer. But those checks can't protect your program from all errors. – Peter Duniho Feb 17 '15 at 07:13
0

100% depends on what you want to achieve.

If a path is invalid and you want to inform it to the user, you can choose between returning a success value or throwing an exception by what's more suitable for your code architecture.

In other cases, where something can go wrong without the user being responsible for it, or needing to be informed, you usually let exceptions get thrown and handle them in catch blocks in the appropriate places.

The thing to remember is that you can always perform an if check and throw an exception of your own in case of invalid state, rather than letting the invalid state cause an exception by itself. The main difference there is in the data thrown with the exception (stack trace, message, etc), but can also be expressed in performance (you wouldn't want to try a high-cost operation if you can first perform a low-cost check to make sure it will succeed). Try-catch blocks add a BIT of an overhead as well, but I wouldn't consider that to be significant.

The questions to ask are:

  • Does invalid state causes the whole operation from above to fail?
  • Where and how does the code handle invalid state?
  • Does the code "fix" the invalid state and tries again?
  • Is the invalid state originating from a user error or a code issue?
  • How costly the operation is, in contrast to how costly the validation check is?

Edit: Check out Yuval's link in the comment to get better understanding of the costs of try-catch blocks.

The validation check is almost always very low-cost, so in conclusion I would say: Perform the check, even if you intend to throw your own exception in case of invalid state.

SimpleVar
  • 14,044
  • 4
  • 38
  • 60
  • 1
    *Try-catch blocks add a BIT of an overhead as well, but I wouldn't consider that to be significant.* I would argue about that. The biggest cost of exceptions is stack-unwinding. If you're deep into a recursive method and need to unwind because the top of the stack has the `catch` block, you're going to pay. [This](http://stackoverflow.com/questions/52312/what-is-the-real-overhead-of-try-catch-in-c) has more about that. – Yuval Itzchakov Feb 17 '15 at 06:34
  • Thanks Yuval, see the edit. Note that in many times exceptions are a better and more logical approach of handling errors, even though they have their cost. As the bigger the call stack, the higher the cost - I usually have handle exceptions in a small-framed fashion. – SimpleVar Feb 17 '15 at 06:40
  • 1
    I'm all for using exceptions when its right. If something bad happens, throw. But for this particular use case, validating the data instead of relying on exceptions would be the more performant and "correct" approach IMO. – Yuval Itzchakov Feb 17 '15 at 06:55
  • I agree, it makes more sense to have a simple `if` in the case that the OP shows, and not have any exception throwing at all. I was just providing a full answer to the question at hand - try-catch vs if – SimpleVar Feb 17 '15 at 07:05