C# 7.0 All-in-One For Dummies
Book image
Explore Book Buy On Amazon
You can define your own custom exception types. Suppose that you want to define a CustomException class. The class might look something like this:

public class CustomException : System.Exception

{

// Default constructor

public CustomException() : base()

{

}

// Argument constructor

public CustomException(String message) : base(message)

{

}

// Argument constructor with inner exception

public CustomException(String message, Exception innerException) :

base(message, innerException)

{

}

// Argument constructor with serialization support

protected CustomException(

SerializationInfo info, StreamingContext context) :

base(info, context)

{

}

}

You can use this basic setup for any custom exception that you want to create. There is no special code (unless you want to add it) because the base() entries mean that the code relies on the code found in System.Exception. What you’re seeing here is the work of inheritance. In other words, for now, you don’t have to worry too much about how this custom exception works. Now consider the catch clause used here:

public void SomeMethod()

{

try

{

SomeOtherMethod();

}

catch(CustomException ce)

{

}

}

What if SomeOtherMethod() had thrown a simple Exception or another non-CustomException type of exception? It would be like trying to catch a football with a baseball glove — the catch doesn’t match the throw.

Fortunately, C# enables the program to define numerous catch clauses, each designed for a different type of exception. Assuming that this is the right place to handle the other exceptions, you can tack on one after another. You must line up the multiple catch clauses for different exception types nose to tail after the try block. C# checks each catch block sequentially, comparing the object thrown with the catch clause’s argument type, as shown in this chunk of code:

public void SomeMethod()

{

try

{

SomeOtherMethod();

}

catch(CustomException ce) // Most specific exception type

{

// All CustomException objects are caught here.

} // You could insert other exception types between these two.

catch(Exception e) // Most general exception type

{

// All otherwise uncaught exceptions are caught here.

// Not that you should always do so -- but when it makes sense ...

}

}

Were SomeOtherMethod() to throw an Exception object, it would pass over the catch(CustomException) because an Exception isn’t a type of CustomException. It would be caught by the next catch clause: the catch(Exception).

Always line up the catch clauses from most specific to most general. Never place the more general catch clause first, as in this fairly awful bit of code:

public void SomeMethod()

{

try

{

SomeOtherMethod();

}

catch(Exception e) // Most general first -- not good!

{

// All exceptions are caught here.

// The dingo ate everything.

}

catch(CustomException ce)

{

// No exception ever gets this far, because it's

// caught and consumed by the more general catch clause.

}

}

The more general catch clause starves the catch clause that follows by intercepting any throw. The compiler alerts you to this error.

Any class that inherits CustomException IS_A CustomException:

class MySpecialException : CustomException

{

// . . . whatever .. .

}

Given the chance, a CustomException catch grabs a MySpecialException object like a frog nabs flies.

About This Article

This article is from the book:

About the book authors:

John Paul Mueller is a writer on programming topics like AWS, Python, Java, HTML, CSS, and JavaScript. William Sempf is a programmer and .NET evangelist. Chuck Sphar was a full-time senior technical writer for the Visual C++ product group at Microsoft.

This article can be found in the category: