All'interno del blocco try si inseriscono istruzioni/chiamate a metodi che potrebbero generare eccezioni (lanciate con l'istruzione throw).
Nei blocchi catch (ce ne può essere più di uno) si inserisce il codice da eseguire in risposta ad ogni tipo di eccezione.
Nel blocco finally si inserisce il codice che verrà *SEMPRE* eseguito, indipendentemente dal fatto che si siano verificate eccezioni o meno.
e se per esempio metto un fclose in un finally, e c'è un errore un try nn mi dà un errore poichè il file nel try nn è stato aperto?
In termini di gestione delle eccezioni il codice contenuto nei blocchi catch o finally è da considerarsi al di fuori del try: se si verifica un'eccezione lì e il blocco try...catch...finally non è incluso in un ulteriore try C# risalirà lo stack delle chiamate alla ricerca di codice di gestione degli errori; in caso non lo trovi il programma terminerà mostrando all'utente un messaggio di errore.
aprendo un file ci può essere l'errore di file inesistente, oppure può darmi un altro tipo di errore qualsiasi, come faccio a sapere di quale errore si tratta? ad esempio se voglio gestire il file inesistente, metto in catch un msgbox con su scritto "file inesistente", e se si tratta di un altro errore??
È ben per questo che ci possono essere più catch:
codice:
using System;
using System.IO;
using System.Windows.Forms;
void Test()
{
FileStream fs;
try
{
fs=File.Create(@"c:\prova\test.txt");
//eccetera
}
catch (DirectoryNotFound ex)
/*Importante: questo blocco catch *DEVE* trovarsi prima del blocco che gestisce IOException, poiché altrimenti l'eccezione DirectoryNotFound verrebbe catturata da esso, in quanto classe derivata da IOException*/
{
MessageBox.Show("Can't find the folder \"prova\".)
}
catch (IOException ex) //dentro alle parentesi si specifica il tipo di eccezione da gestire e l'oggetto che ne conterrà i dati
{
MessageBox.Show("IO Exception: " + ex.Message);
}
catch (Exception ex)
/*Tutte le eccezioni sono classi derivate da System.Exception, per cui tutto ciò che non è stato gestito prima viene catturato adesso.
Ovviamente questa deve essere l'ultima catch del blocco try...catch...finally*/
{
MessageBox("Generic exception: " + ex.Message);
}
finally
{
//Se il file è stato effettivamente aperto lo chiude
if (!(fs==null)) fs.Close();
}
Questa è solo una overview di questo costrutto estremamente versatile su cui si basa tutta la gestione degli errori di C# e di molti altri linguaggi .NET. Ti consiglio di dare un'occhiata ai seguenti link:

e soprattutto di comprarti un buon libro su C#.