<p>I have seen people say that it is bad form to use catch with no arguments, especially if that catch doesn't do anything:</p>

<pre><code>StreamReader reader=new  StreamReader("myfile.txt");
try
{
  int i = 5 / 0;
}
catch   // No args, so it will catch any exception
{}
reader.Close();
</code></pre>

<p>However, this is considered good form:</p>

<pre><code>StreamReader reader=new  StreamReader("myfile.txt");
try
{
  int i = 5 / 0;
}
finally   // Will execute despite any exception
{
  reader.Close();
}
</code></pre>

<p>As far as I can tell, the only difference between putting cleanup code in a finally block and putting cleanup code after the try..catch blocks is if you have return statements in your try block (in that case, the cleanup code in finally will run, but code after the try..catch will not).</p>

<p>Otherwise, what's so special about finally?</p>

"Finally" is a statement of "Something you must always do to make sure program state is sane". As such, it's always good form to have one, if there's any possibility that exceptions may throw off the program state. The compiler also goes to great lengths to ensure that your Finally code is run.
"Catch" is a statement of "I can recover from this exception". You should only recover from exceptions you really can correct - catch without arguments says "Hey, I can recover from anything!", which is nearly always untrue.
If
it were possible to recover from every exception, then it would really be a semantic quibble, about what you're declaring your intent to be. However, it's not, and almost certainly frames above yours will be better equipped to handle certain exceptions. As such,   use finally, get your cleanup code run for free, but still let more knowledgeable handlers deal with the issue.