The .NET runtime has raised an exception, meaning something has occured that normally shouldn't. Why did this happen? You want to learn ways not just to catch the exception, but to prevent it from happening. What specific exceptions are there, and how can you investigate them?
An exception's name is the first big clue. The first example I will cover is about using variables (objects) when they are null. Any programmer will know that "null" values used incorrectly often lead to crashes.
It means you have a null object you are trying to use. You can't do that. This exception can be hard to debug. Next are some examples, and then I point out when this occurs in programs. This is raised when you call an instance method on a null object.
/// <summary>
/// Demonstrates what happens when a method is called on a null variable.
/// </summary>
public void ExampleA()
{
string exampleValue = null;
exampleValue.Trim();
//
// Raises exception. (See more on Trimming strings.)
//
}
/// <summary>
/// Sometimes, we shouldn't check for null.
/// </summary>
public void ExampleB()
{
try
{
//
// This code will never fail in normal conditions.
//
string value = MethodReturnsNull();
value = value.Trim();
}
catch (NullReferenceException)
{
//
// The 'value' really shouldn't be null in normal conditions.
// A serious flaw in the design or deployment occured.
//
}
}
It means you are accessing a memory location that's not initialized. One fix is to use bounds-checking on a getter or setter. However, if the error condition is unlikely to happen, it is more efficient and graceful to handle it through try and catch blocks. In the following example, you should change the max value of the loop.
/// <summary>
/// If you use the square brackets and an index that isn't present
/// in the array or collection, you will go out of range.
/// </summary>
public void ExampleC()
{
//
// This will raise an index out of range exception.
//
string example = "cat";
for (int i = 0; i < 10; i++)
{
Console.WriteLine(example[i]);
}
}
To avoid exceptions like the ones above. With a foreach loop, another function takes control of the iteration process. You don't need to know the collection's indexes. Here are some solutions to the IndexOfOutRange exception.
/// <summary>
/// Some ways to solve an out of range exception.
/// </summary>
public void ExampleD()
{
string example = "cat";
//
// use try/catch
//
try
{
for (int i = 0; i < 10; i++)
{
Console.WriteLine(example[i]);
}
}
catch (IndexOutOfRangeException)
{
return;
}
//
// or move to enumerators and foreach
//
foreach (char c in example)
{
Console.WriteLine(c);
}
}
Change your code to use generic objects that specify the type. Alternatively, use the special 'as' or 'is' operators. This often occurs when you are dealing with object types (the object type that everything in C# inherits from). When you try to use that object as something it is not, it will throw this exception.
/// <summary>
/// This nasty example shows one way you can get into trouble with
/// casting and get an InvalidCastException.
/// </summary>
public void ExampleE()
{
string box = "cat";
object general = box as object;
int a = (int)general;
}
/// <summary>
/// This code shows you how to avoid the exception and only cast to
/// int when you are sure the object is an int.
/// </summary>
public void ExampleF()
{
string box = "cat";
object general = box as object;
int a = 0;
if (general is int)
{
a = (int)general;
}
}
It means the file is not on the disk. I want to show a couple examples of code blocks that may be causing this exception. When you assume a file is present and it isn't, you will get this exception. Simply add logic to File.Exists for this case, or if the situation is really abnormal, catch this exception.
/// <summary>
/// Example class.
/// </summary>
class ExceptionClass
{
/// <summary>
/// This shows what NOT to do. We want to have error handling instead of this
/// kind of code. Also, you usually shouldn't need File.Open.
/// </summary>
public void ExampleG()
{
//
// Example file not found exceptions raised here.
//
File.Open("not-there.txt", FileMode.Open);
using (StreamReader reader = new StreamReader("not-there.txt"))
{
reader.ReadToEnd();
}
//
// This is a DirectoryNotFoundException.
//
Directory.GetDirectories("C:\\Nonexistant");
}
}
Here we deal with FileNotFoundException. I recommend using this kind of exception over File.Exists() when it is unlikely that the file will not be found. The exception seems to encourage clearer code that is easier to follow and maintain.
/// <summary>
/// This is how to deal with a nonexistent file.
/// </summary>
public void ExampleH()
{
try
{
//
// Demonstrates using StreamReader syntax.
//
using (StreamReader reader = new StreamReader("not-there.txt"))
{
reader.ReadToEnd();
}
}
catch (FileNotFoundException)
{
//
// you can tell the user her file was not found.
//
Console.WriteLine("Your file was not found. Make a new one?");
//
// Read more about file handling...
//
}
}
An exception that's thrown when a directory isn't found. The DirectoryNotFoundException is thrown when a method, most commonly Directory.GetDirectories(), receives an invalid path. Programs like Paint.NET use a method that ensures the directory exists.
The key doesn't exist in the Dictionary. You can fix with the TryGetValue method or simply more error checking. Add some debugging points in your application and try to find out if you assign to a key that doesn't exist in your Dictionary object. You must use the Add method to put a value in the collection with a key.
/// <summary>
/// This is one very common pattern that can screw up a program.
/// </summary>
public void ExampleI()
{
Dictionary<string, string> dict = new Dictionary<string, string>();
dict.Add("one", "value");
string test = dict["two"];
}
/// <summary>
/// This is how you should code the Dictionary lookup. It is longer, but
/// this is the recommended way, by much smarter people than I.
/// </summary>
public void ExampleJ()
{
Dictionary<string, string> dict = new Dictionary<string, string>();
dict.Add("one", "value");
//
// Use TryGetValue for performance.
//
string test;
if (dict.TryGetValue("two", out test))
{
//
// test is set
//
}
test = null;
}
You could be using recursion or some part of your algorithm may be out of control. If you are experiencing a stack overflow exception, there is a very serious problem with your code. Your method may call itself endlessly, or two methods may call each other. The problem is probably in your algorithm.
Here's a list of them. These exceptions are thrown by ADO.NET provider objects. They involve some of my most frustrating moments as a developer. When you get one of these following exceptions, you may be using invalid SQL. The SQL engine may or may not provide more details.
There are places where exceptions are not required, and debugging statements are better. Our first task is to gain knowledge about the exceptions thrown by the runtime, and our second task is simply to catch them or avoid them in the first place.