Exceptions Programming in C# Exceptions CSE 494R (proposed course for 459 Programming in C#) Prof....

Preview:

Citation preview

Programming in C#ExceptionsExceptions

CSE 494R(proposed course for 459 Programming in C#)

Prof. Roger Crawfis

Slides are not finished

Not sure we will cover this topic.

Exceptional Situations

Sometimes, runtime errors are caused by unusual situations, not programming errors

For example: writing data to a fileMost of the time things go uneventfully, but...

The disk may be fullThere may be a hardware errorThe file may have been changed to read-only

Fragile code ignores the possibility of problems

Robust code anticipates such problems

The Traditional Method I

Traditional way of handling is to use "completion codes"

GET A FILENAMEOPEN THE FILEIF THERE IS NO ERROR OPENING THE FILE

READ SOME DATAIF THERE IS NO ERROR READING THE DATA

PROCESS THE DATAWRITE THE DATAIF THERE IS NO ERROR WRITING THE DATA

CLOSE THE FILEIF THERE IS NO ERROR CLOSING FILE

RETURN

The Traditional Method II

Things to notice with completion codesAlmost every step may fail, except "PROCESS

DATA"Program just be prepared to deal with failure

Very difficult to determine "normal" actionsSo concerned with things that can go wrong that it is hard

to tell if you are doing the right things in the right order

Difficult to use if library function contains such codeFunction must return several error codes so that user can

tell what went wrong

The Exceptional Method

Using exceptions the code looks like this

TRY TO DO THESE THINGS: GET A FILENAME OPEN THE FILE READ SOME DATA PROCESS THE DATA WRITE THE DATA CLOSE THE FILERETURNIF ERROR OPENING THE FILE THEN ...IF ERROR READING THE DATA THEN ...IF ERROR WRITING THE DATA THEN ...IF ERROR CLOSING THE FILE THEN ...

Exception Advantages

Compare methods of handling "bad things"Code that uses the exception strategy:

Is shorter and easier to readMakes the normal logic the main focus of the

method. In the completion code version, the error-handling code obscures the normal actions

Allows you to decide whether to handle the problem or defer handling the error on a case-by-case basis

Ideal for library-based code

Exception Objects

In C#, when a runtime error occursThe CLR sees the problem and creates an

ExceptionExceptionObject is from a subclass of System.ExceptionSystem.ExceptionClass ApplicationExceptionApplicationException : extend & recoverClass SystemExceptionSystemException : fix by proper coding

The exception object is thrown back up the call stack until a method is found that wants to catch it

If it is not "caught" then the CLR runtime system prints an error message

Following Exceptions

CLR Runtime

The Main( )method

First Method

ExceptionThrown Here

MethodCallsTravelDown

ExceptionsPassed

Up

Using try-catch

In C#, you handle exceptions with try-catchtry-catchPut the code that may cause an exceptional

situation into a “trytry” block.

Provide one or more “catchcatch” blocks immediately following the “trytry” block

You should provide catchcatch blocks for all errors you want to handle. Do this by choosing to catch particular classes.

If you don’t provide a catchcatch block for a particular exception, then the exception will be propagated up

The try-catch Syntax

08OOP12.WMF Figure 8-12 The try-catch

try { riskyBusiness(); } catch (SomeException e) { // Handle bad stuff }

Braces

Keyword

Braces

Statements or methods that maythrow exceptions

Keyword

Exceptionargument to becaught

Statements to deal with exceptional situation

The try block

The trytry block consists of:The keyword trytryFollowed by a brace-delimited blockBraces are required: part of the syntax

This is unlike loops and ifif statements

Inside the trytry blockPlace any number of statements that may

throw an exception

The catch Block

Place one or more immediately following trytry Nothing but whitespace or comments between

Syntax for catchcatch block is a little tricky

catch (Exception-Class [var1])catch (Exception-Class [var1]){{ // Handle exception 1 here// Handle exception 1 here}}catch (Exception-Class [var2])catch (Exception-Class [var2]){{ // Handle exception 2 here// Handle exception 2 here}}

A try-catch Example

Example : DivideByZeroTest.csFind on Q: drive in folder ch11\Fig11_01Drag and drop on F: or U: drive

Method Convert.ToInt32()Convert.ToInt32() will automatically detect for invalid representation of an integerMethod generates a FormatExceptionFormatException

CLR automatic detection for division by zeroOccurrence will cause a

DivideByZeroExceptionDivideByZeroException

Now, Finally, finally

When an exception is thrownControl jumps to the catchcatch block that handles itCode that releases resources may be skipped

Open FileOpen FileRead Data Read Data // Exception thrown here// Exception thrown hereClose File Close File // This is skipped. File still // This is skipped. File still openopen

The try-catchtry-catch has an optional finallyfinally partThis will always be calledUse to handle resource depletion

08OOP16.WMF Figure 8-16 The try-catch-finally

try { SomeResource thing; doSomethingWith(thing); } catch (SomeException e) { // Cope with tragic failure } finally { // This ALWAYS happens releaseResource(thing); }

Braces

Keyword

Braces

Statements or methods that maythrow exceptions

Keyword

Exceptionargument to be

caught

Statements to deal withexceptional situation

Braces

Keyword

Statements thatalways get executed

Throwing Exceptions

You aren't restricted to try-catch-finallytry-catch-finallyYou can throw exceptions as wellMust be an ExceptionException object or a subclass

if (numerator == 0)if (numerator == 0)throw new Exception("Illegal throw new Exception("Illegal

numerator");numerator");

You can rethrow a caught exception as wellExample: Figure 11-2, UsingExceptions.cs

Exception Object Properties

Properties for a caught exception [ Properties.cs ] MessageMessage : error message associated with an

exceptionMay be a default message or customized

StackTraceStackTrace : string representing the method call

stackList of "pending" methods when the exception occurredThe exact location is called the throw point

InnerExceptionInnerException property “Wrap” exception objects caught in codeThen throw new exception types

Defining Your Own Exceptions

Your program may have "application-specific" exceptions

To define your own exception classesDerive a new class from ApplicationExceptionApplicationException

For consistencies sake, name should end with “Exception”Should define three constructors

A default constructorA constructor that receives a string argumentA constructor that takes a string and an Exception argument

Example: NegativeNumberException.cs

Handling Integer Overflow

Traditionally, integer overflow is not a runtime error If a result is too large the answer is silently truncated

int ans = 400000 * 400000 / 400000;int ans = 400000 * 400000 / 400000;

C# allows you to change this on a calc-by-calc basis

int ans = checked( 400000 * 400000 / 400000);int ans = checked( 400000 * 400000 / 400000);

Throws an OverflowExceptionOverflowExceptionThere is a matching unchecked()unchecked() operatorExample: Overflow.cs

Exceptions in C#

Must inherit from System.Exception

Standard error handling in C#

Are thrown when: the code reaches a throw statement System exceptions occur (such as divide by zero)

No checked exceptions or exception specifications

Creating an Exception Class

Inherit ultimately from System.Exception

public class Exception1 : System.Exception{ public Exception1(string message) : base(message){}}

public class SomeException : Exception1{ public SomeException(string message) : base(message){}}

throw statement

Must throw an instance of an exception:throw(new MyException(“Error”));

May be used by itself only in a catch block: catch

{

throw;

}

Catching an Exception

A catch block is associated with a try block

A try block may have more than one catch block

catch blocks catch the exception type or any derived exception types passing through catch blocks are searched in the order they appear in the code catch blocks for specific types must come before the more general

types

An Empty catch clause will catch any type

catch clauses don’t need a variable name catch(Exception) is ok

catch blocks

void function1(){ try { // code } catch(Exception1 ex) { } catch(Exception ex) { }

// if no rethrow occurs // execution resumes here}

void function1(){ try { // code } catch(Exception ex) { } catch(Exception1 ex) { }}

Wrong Right

Exception Flow Control

void function1(){ try { try { throw(new SomeOtherException(“Error Message”)); } catch(Exception1 ex) { } } catch(Exception2 ex) { }}

The exception is passed up the call-stack until a suitable handler is found

Exception Flow Control

void function2(){ try { Function1(); } catch(Exception3 ex3) { } catch(Exception2 ex4) { } catch(Exception ex) { }}

If no suitable handler (catch clause) was found, the exception is passed to the calling method

Unhandled Exceptions

If no error handler is found the application terminates Control is passed back to Windows

finally block

Must be associated with a try block

a try block may have only one finally block

finally block always gets executed The appropriate catch clause is executed first

finally Flow Controlvoid function1(){ try { try { throw(new SomeException(“Error Message”)); } catch(Exception1 ex) { } finally { } } catch(Exception2 ex) { } finally { }}

Some Special Rules

Unhandled Exception in a destructor destructor stops executing, exception is discarded, base destructor is

called

catch (with no parameter) will catch unmanaged exceptions from other languages

Library Exceptions

Feel free to use these: ArithmeticException ArrayTypeMismatchException DivideByZeroException IndexOutOfRangeException InvalidCastException NullReferenceException OutOfMemoryException OverflowException StackOverflowException TypeInitializationException

System.Exception Class

Message string message associated with the exception

InnerException If this exception was generated inside an exception handler,

this refers to the original exception

Source Refers to the source class

StackTrace String representing the call stack, file and line number

Breaking On Exceptions

Debug | Exceptions (or Ctrl + D, E)

Exception Handling

Provides tremendous benefits

Requires a different way of thinking

The old way

RETVAL Process(int a, int x, int y, int z){RETVAL retval;if ((retval = function(x, y, z)) != OK)

return retval;

if ((retval = function2(a, y)) != OK)return retval;

}

Option 1

void Process(int a, int x, int y, int z){ try {

function(x, y, z);}catch (Exception e){

throw e;}

try {

function2(a, y);}catch (Exception e){

throw e;}

}

Option 2

void Process(int a, int x, int y, int z){ try {

function(x, y, z);function2(a, y);

}catch (Exception e){

throw e;}

}

Option 3

void Process(int a, int x, int y, int z){

function(x, y, z);function2(a, y);

}

Exception Handling

You get correct behavior by defaultOnly catch an exception when you can do

something useful for the userYou can write lots of unnecessary code, but

at least your code will be less robust

When to catch

Something specific happens, and we can help

trytry{{ StreamReader s = File.OpenText(filename);StreamReader s = File.OpenText(filename);}}

catch (Exception e)catch (Exception e){{ Console.WriteLine(“Invalid filename: {0}”, filename);Console.WriteLine(“Invalid filename: {0}”, filename);}}

trytry{{ StreamReader s = File.OpenText(filename);StreamReader s = File.OpenText(filename);}}

catch (FileNotFoundException e)catch (FileNotFoundException e){{ Console.WriteLine(e);Console.WriteLine(e);}}

trytry{{ ExecuteBigProcess();ExecuteBigProcess();}}

catch (Exception e)catch (Exception e){{ log.WriteLine(e.ToString());log.WriteLine(e.ToString()); throw;throw;}}

trytry{{ ExecuteBigProcess();ExecuteBigProcess();}}

catch (Exception e)catch (Exception e){{ throw new throw new MyException(“Error executing BigProcess”, e); MyException(“Error executing BigProcess”, e);}}

When to catch

We need to log or wrap an exception

When to catch

Process would die otherwisepublic static void Main()public static void Main(){{ while (true)while (true) {{ trytry {{ MainLoop();MainLoop(); }} catch (Exception e)catch (Exception e) {{ Console.WriteLine(“Exception caught, trying to continue”);Console.WriteLine(“Exception caught, trying to continue”); Console.WriteLine(e);Console.WriteLine(e); }} }}}}

Finally statement

If an exception is thrown andThere’s something to clean up

Close a fileRelease a DB handle

Using statement makes this easierWorks on anything that implements IDisposable

Using Statement

Acquire, Execute, Release patternWorks with any IDisposable object

Data access classes, streams, text readers and writers, network classes, etc.

using (Resource res = new Resource()) {using (Resource res = new Resource()) { res.DoWork();res.DoWork();}}

Resource res = new Resource(...);Resource res = new Resource(...);try {try { res.DoWork();res.DoWork();}}finally {finally { if (res != null) ((IDisposable)res).Dispose();if (res != null) ((IDisposable)res).Dispose();}}

Using Statement

static void Copy(string sourceName, string destName) {static void Copy(string sourceName, string destName) { Stream input = File.OpenRead(sourceName);Stream input = File.OpenRead(sourceName); Stream output = File.Create(destName);Stream output = File.Create(destName); byte[] b = new byte[65536];byte[] b = new byte[65536]; int n;int n; while ((n = input.Read(b, 0, b.Length)) != 0) {while ((n = input.Read(b, 0, b.Length)) != 0) { output.Write(b, 0, n);output.Write(b, 0, n); }} output.Close();output.Close(); input.Close();input.Close();}}

static void Copy(string sourceName, string destName) {static void Copy(string sourceName, string destName) { Stream input = File.OpenRead(sourceName);Stream input = File.OpenRead(sourceName); try {try { Stream output = File.Create(destName);Stream output = File.Create(destName); try {try { byte[] b = new byte[65536];byte[] b = new byte[65536]; int n;int n; while ((n = input.Read(b, 0, b.Length)) != 0) {while ((n = input.Read(b, 0, b.Length)) != 0) { output.Write(b, 0, n);output.Write(b, 0, n); }} }} finally {finally { output.Close();output.Close(); }} }} finally {finally { input.Close();input.Close(); }}}}

static void Copy(string sourceName, string destName) {static void Copy(string sourceName, string destName) { using (Stream input = File.OpenRead(sourceName))using (Stream input = File.OpenRead(sourceName)) using (Stream output = File.Create(destName)) {using (Stream output = File.Create(destName)) { byte[] b = new byte[65536];byte[] b = new byte[65536]; int n;int n; while ((n = input.Read(b, 0, b.Length)) != 0) {while ((n = input.Read(b, 0, b.Length)) != 0) { output.Write(b, 0, n);output.Write(b, 0, n); }} }}}}

Exceptions vs Return Codes

Exceptions are meant for exceptional cases Invalid parametersCan’t perform operation

Should not occur during normal program operationUser interaction is a grey area

Using Return Values

Okay if your caller always will have to check and recover from somethingMake sure you don’t force them to write:

Shouldn’t be possible to do the wrong thingFile.Open() returns null on file not foundYou can’t ignore this

bool success = TryOperation(param1, param2);bool success = TryOperation(param1, param2);if (!success)if (!success) return success;return success;

Summary

Understand how the model worksDon’t work too hardIf you can’t do something useful, don’t

catch

Programming in C# ExceptionsExceptions

CSE 494R(proposed course for 459 Programming in C#)

Prof. Roger Crawfis

Programming in C#XML DocumentationXML Documentation

CSE 494R(proposed course for 459 Programming in C#)

Prof. Roger Crawfis

Programming in C# XML DocumentationXML Documentation

CSE 494R(proposed course for 459 Programming in C#)

Prof. Roger Crawfis

Recommended