In most cases, you don’t have to worry about the type of exception that you get, so catching a general Exception fine, however, there are specific situations in which you really would like to catch the corresponding exception (and not just the general Exception ).
One specific example: if you have a thread and you want to interrupt it from a blocking call, in this case you need to distinguish between InterruptException and Exception .
Consider this example: you have a thread that runs Read every minute for 5 minutes (this is not a very realistic example, but it should give you an idea of why you want to handle different exceptions). You have to stop the thread after 5 minutes, because your application will be closed, and you do not want to wait another minute for the running flag to be read ... after all, you do not want your user to wait only a minute to close the application. To stop a thread immediately, you set the flag to false and you call Interrupt on your thread. In this case, you need to catch the ThreadInterrupted exception because it tells you that you should exit the loop. If you catch another exception, then you will not be able to complete the task, but you do not want to give up on work together, and you would like to try and read the next minute again. This shows how your requirements determine the type of exceptions you need to handle. Here is a sample code:
bool running = true; Thread t = new Thread(()=> { while(running) { try { // Block for 1 minute Thread.Sleep(60*1000); // Perform one read per minute personsReader.Read(filename, persons); } catch (KeyNotFoundException e) { // Perform a specific exception handling when the key is not found // but do not exit the thread since this is not a fatal exception MessageBox.Show(e.Message); } catch(InterruptException) { // Eat the interrupt exception and exit the thread, because the user // has signalled that the thread should be interrupted. return; } catch(Exception e) { // Perform a genetic exception handling when another exception occurs // but do not exit the thread since this is not a fatal error. MessageBox.Show("A generic message exception: " + e.Message); } } }); t.IsBackground = true; t.Start(); // Let the thread run for 5 minutes Thread.Sleep(60*5000); running = false; // Interrupt the thread t.Interrupt(); // Wait for the thread to exit t.Join();
Now about your other problem, if the exception is not displayed: note that you are referring to person[e.Name.ToString()] = e.Value , which requires a key search, and if the key is not on the map, you can get a KeyNotFoundException . This will be a general exception that you catch, and your custom exception will never be thrown, because person[e.Name.ToString()] can throw before you even get into your code.
foreach (XElement e in person) person[e.Name.ToString()] = e.Value; // <-- May be throwing the KeyNotFoundException if (person["Name"] == null || person["Job"] == null || person["HairColor"] == null) throw new KeyNotFoundException("Person element not found.");
In addition, you do not want to throw a KeyNotFoundException when you really found the key, but you did not find the corresponding value: if person["Name"] == null evaluates to true, then the "Name" key was actually found in the person dictionary, so throwing KeyNotFoundException will mislead anyone who catches this exception. In case your value is null , then it would probably be impractical to throw an exception ... this is really not an exceptional case. You can return a flag indicating that the key was not found:
public bool PerformRead(/*... parameters ...*/) { foreach (XElement e in person) { // Avoid getting the KeyNotFoundException if(!person.ContainsKey(e.Name.ToString())) { person.Add(e.Name.ToString(), "some default value"); } person[e.Name.ToString()] = e.Value; } if (person["Name"] == null || person["Job"] == null || person["HairColor"] == null) { return false; } else { return true; } }