.NET does exceptions instead of the error codes in VB6. If your program doesn't handle the exceptions, it gets sent to the OS where it triggers a (tada!) "unhandled exception" error. Which end users usually call a "crash" but to a programmer means a problem happened that they should have caught in their error handling code.
See
this article.
Error handling is a whole topic in itself, since you can write "correct" code that becomes impossible to maintain because of all the try/catch blocks you have to put everywhere. But basically you should architect your program so that:
1. End users can't cause any exceptions (sanitize user input). 99% of the time, when a user plays with your program no exceptions should be thrown. So basically, don't use exceptions for things you expect to happen.
2. When an exception does occur, it's caught
at least at the top level of your program so you can gracefully respond (eg: "a problem has occurred, saving sim..."). With .NET it's also possible to examine the exception to get a call stack complete with file names and line numbers.
3. If anything at all unexpected happens, it throws an exception instead of trying to mask the problem and continuing (allows early detection of problems and easier debugging).
Another good article:
clicky.