Generally, for nearly everything to do with file systems, the trick is to remember they are volatile, and therefore the answer is to just try
whatever you want to do and handle the exception if it fails.
To understand what I mean by, "volatile", let's say you have some magic Path.IsReadOnlyFileSystem()
method that does exactly what you want. So you want to run some code like this:
if (!Path.IsReadOnlyFileSystem(fileIWantToCreate))
{
using(var sw = new StreamWriter(fileIWantToCreate))
{
//fill file here
}
}
But then something happens in your AWS cloud forcing the service to go into read-only mode. And it happens right here:
if (!Path.IsReadOnlyFileSystem(fileIWantToCreate))
{
/* <==== AWS goes read-only here ====> */
using(var sw = new StreamWriter(fileIWantToCreate))
Your magic method did it's job perfectly. At the moment you called the method, the file system still allowed writes. Unfortunately, a volatile file system means you can't trust operations from one moment to the next (and a non-volatile file system wouldn't be much good to you for saving data). So you might be tempted to go for a pattern like this:
try
{
if (!Path.IsReadOnlyFileSystem(fileIWantToCreate))
{
using(var sw = new StreamWriter(fileIWantToCreate))
{
//fill file here
}
}
}
catch( )
{
// handle the exception here
}
And now it's clear you have to handle the exception anyway. The if()
condition doesn't really gain anything in terms of actual functionality. All it really does is add complexity to your code.
Even so, there's a tendency to believe keeping the if()
condition gains a performance benefit by saving an exception handler and saving a disk access. This belief is flawed.
The if()
condition actually adds disk access when it checks the file system status. Moreover, this cost is added on every execution. Keeping the if()
condition does save the exception handler, but only on occasions where the initial access fails. Admittedly, unrolling the stack to handle an exception is among the most expensive operations you can do in all of computer science. This is the "why" behind the "don't use exceptions for normal control flow" mantra. However, disk access is one of the few things that is far and away worse for performance.
In summary, we have an exception handler stack unwind sometimes vs an extra disk access every time. From a performance standpoint it's clear you're better off without the if()
condition at all. We don't need the if()
condition for correctness reasons, and we don't want it for performance reasons.... remind me again why we have it? The better pattern skips that block completely, like this:
try
{
using(var sw = new StreamWriter(fileIWantToCreate))
{
//fill file here
}
}
catch( )
{
// handle the exception here
}
Thus the magic IsReadOnlyFileSystem()
method is not needed or even helpful.
This isn't to say that method doesn't exist (I don't think it's part of .Net Standard, but depending on your platform there's likely a lower-level construct you can call into). It's just that it's not a particularly good idea.