204111 Computer and Programming Lecture # 09: Strings and - - PowerPoint PPT Presentation

204111 computer and programming
SMART_READER_LITE
LIVE PREVIEW

204111 Computer and Programming Lecture # 09: Strings and - - PowerPoint PPT Presentation

204111 Computer and Programming Lecture # 09: Strings and Characters Name Spaces, Enum, Struct Try-Catch Block http: / / mike.cpe.ku.ac.th/ 204111 TM approved MI KE Class String A string is essentially an encapsulation of an array of


slide-1
SLIDE 1

MI KE

TM approved

204111 Computer and Programming

Lecture # 09:

Strings and Characters Name Spaces, Enum, Struct Try-Catch Block

http: / / mike.cpe.ku.ac.th/ 204111

slide-2
SLIDE 2

2 MI KE

TM approved

Version 2005/2

Class String

A string is essentially an encapsulation of

an array of characters.

since we use string so often, C# defines the

string class and provides many methods (behaviors).

We have already seen several methods:

method ToUpper

replaces lower case letter

  • riginal string remains unchanged

method ToLower

replaces lower case letter

  • riginal string remains unchanged
slide-3
SLIDE 3

3 MI KE

TM approved

Version 2005/2

Class String: Creating New Strings

Constructors

C# provides eight constructors for initializing

strings.

CopyTo method

copies specified number of characters into a

char array.

Substring method

extracts a sub string.

Concat method

Combine two strings.

slide-4
SLIDE 4

4 MI KE

TM approved

Version 2005/2

using System; using System.Windows.Forms; class StringConstructor { static void Main( string [] args ) { string output; string originalString, string1, string2, string3, string4; char [] characterArray = { 'b', 'i', 'r', 't', 'h', ' ', 'd', 'a', 'y' }; // string initialization

  • riginalString = "Welcome to C# programming!";

string1 = originalString; string2 = new string( characterArray ); string3 = new string( characterArray, 6, 3 ); string4 = new string( 'C', 5 ); // combined output

  • utput = "string1 = " + "\"" + string1 + "\"\n" +

"string2 = " + "\"" + string2 + "\"\n" + "string3 = " + "\"" + string3 + "\"\n" + "string4 = " + "\"" + string4 + "\"\n"; MessageBox.Show( output, "String Class Constructors", MessageBoxButtons.OK, MessageBoxIcon.Information ); } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19

slide-5
SLIDE 5

5 MI KE

TM approved

Version 2005/2

StringConstructor.cs

slide-6
SLIDE 6

6 MI KE

TM approved

Version 2005/2

using System; using System.Windows.Forms; class StringMethods { static void Main(string [] args ) { string string1, output; char [] characterArray; string1 = "hello there"; characterArray = new char [5];

  • utput = "string1: \"" + string1 + "\"";
  • utput += "\nLength of string1: " + string1.Length;
  • utput += "\nThe string reversed is: ";

for ( int i = string1.Length - 1; i >= 0; i-- )

  • utput += string1[i];

string1.CopyTo(0, characterArray, 0, 5);

  • utput += "\nThe character array is: ";

for ( int i = 0 ; i < characterArray.Length; i++ )

  • utput += characterArray[i];

MessageBox.Show(output, "Demonstrating the string " + "Indexer, Length Property and CopyTo method", MessageBoxButtons.OK, MessageBoxIcon.Information); } // end method Main } // end class StringMethods 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20

slide-7
SLIDE 7

7 MI KE

TM approved

Version 2005/2

StringMethods.cs

slide-8
SLIDE 8

8 MI KE

TM approved

Version 2005/2

using System; using System.Windows.Forms; class SubString { static void Main(string [] args) { string letters = "abcdefghijklmabcdefghijklm"; string output = "";

  • utput += "Substring from index 20 to end is \""

+ letters.Substring(20) + "\"\n";

  • utput += "Substring from index 0 to 6 is \""

+ letters.Substring(0, 6) + "\""; MessageBox.Show(output, "Demonstrating String method Substring", MessageBoxButtons.OK, MessageBoxIcon.Information); } // end method Main } // end class SubString 1 2 3 4 5 6 7 8 9 10 11

slide-9
SLIDE 9

9 MI KE

TM approved

Version 2005/2

SubString.cs

slide-10
SLIDE 10

10 MI KE

TM approved

Version 2005/2

using System; using System.Windows.Forms; class StringConcatenation { static void Main(string [] args) { string string1 = "Happy "; string string2 = "Birthday"; string output;

  • utput = "string1 = \"" + string1 + "\"\n" + "string2 = \"" + string2 + "\"";
  • utput += "\n\nResult of String.Concat(string1, string2) = "

+ String.Concat(string1, string2);

  • utput += "\nstring1 after concatenation = " + string1;

MessageBox.Show(output, "Demonstrating String method Concat", MessageBoxButtons.OK, MessageBoxIcon.Information); } // end method Main } // end class StringConcatenation 1 2 3 4 5 6 7 8 9 10 11 12 13

slide-11
SLIDE 11

11 MI KE

TM approved

Version 2005/2

SubConcatination.cs

slide-12
SLIDE 12

12 MI KE

TM approved

Version 2005/2

Class String: Comparison and string Search

Comparison

Methods CompareTo and Equals

uses lexicographical comparison.

Methods StartsWith and EndsWith

Find the position of a char or string

IndexOf IndexOfAny LastIndexOf LastIndexOfAny

slide-13
SLIDE 13

13 MI KE

TM approved

Version 2005/2

using System; using System.Windows.Forms; class StringCompare { static void Main(string [] args) { string string1 = "hello"; string string2 = "good bye"; string string3 = "Happy Birthday"; string string4 = "happy birthday"; string output;

  • utput = "string1 = \"" + string1 + "\"" + "\nstring2 = \"" + string2 + "\"" +

"\nstring3 = \"" + string3 + "\"" + "\nstring4 = \"" + string4 + "\"\n\n"; if (string1.Equals("hello")) output += "string1 equals \"hello\"\n"; else output += "string1 does not equal \"hello\"\n"; if (string1 == "hello") output += "string1 equals \"hello\"\n"; else output += "string1 does not equal \"hello\"\n"; if (String.Equals(string3, string4)) output += "string3 equals string4\n"; else output += "string3 does not equal string4\n";

  • utput += "\nstring1.CompareTo(string2) is " + string1.CompareTo(string2) + "\n" +

"string2.CompareTo(string1) is " + string2.CompareTo(string1) + "\n" + "string1.CompareTo(string1) is " + string1.CompareTo(string1) + "\n" + "string3.CompareTo(string4) is " + string3.CompareTo(string4) + "\n" + "string4.CompareTo( string3 ) is " + string4.CompareTo(string3) + "\n\n"; MessageBox.Show(output, "Demonstrating string " + "comparisons", MessageBoxButtons.OK, MessageBoxIcon.Information); } // end method Main } // end class StringCompare 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17

slide-14
SLIDE 14

14 MI KE

TM approved

Version 2005/2

StringCompare.cs

slide-15
SLIDE 15

15 MI KE

TM approved

Version 2005/2

using System; using System.Windows.Forms; class StringStartEnd { static void Main(string [] args) { string [] strings = {"started", "starting", "ended", "ending"}; string output = ""; for (int i = 0; i < strings.Length; i++) if (strings[i].StartsWith("st"))

  • utput += "\"" + strings[i] + "\"" + " starts with \"st\"\n";
  • utput += "\n";

for (int i = 0; i < strings.Length; i ++) if (strings[i].EndsWith("ed"))

  • utput += "\"" + strings[i] + "\"" + " ends with \"ed\"\n";

MessageBox.Show(output, "Demonstrating StartsWtih and " + "EndsWith methods", MessageBoxButtons.OK, MessageBoxIcon.Information); } // end method Main } // end class StringStartEnd 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16

slide-16
SLIDE 16

16 MI KE

TM approved

Version 2005/2

StringStartEnd.cs

slide-17
SLIDE 17

17 MI KE

TM approved

Version 2005/2

using System; using System.Windows.Forms; class StringIndexMethods { static void Main(string [] args) { string letters = "abcdefghijklmabcdefghijklm"; string output = ""; char [] searchLetters = {'c', 'a', '$'};

  • utput += "'c' is located at index " + letters.IndexOf('c');
  • utput += "\n'a' is located at index " + letters.IndexOf('a', 1);
  • utput += "\n'a' is located at index " + letters.IndexOf('a', 3, 5);
  • utput += "\n\nLast 'c' is located at " + "index " + letters.LastIndexOf('c');
  • utput += "\nLast 'a' is located at index " + letters.LastIndexOf('a', 25);
  • utput += "\nLast '$' is located at index " + letters.LastIndexOf('$', 15, 5);
  • utput += "\n\n\"def\" is located at" + " index " + letters.IndexOf("def");
  • utput += "\n\"def\" is located at index " + letters.IndexOf("def", 7);
  • utput += "\n\"hello\" is located at index " + letters.IndexOf("hello", 5, 15);
  • utput += "\n\nLast \"def\" is located at index " + letters.LastIndexOf("def");
  • utput += "\nLast \"def\" is located at " + letters.LastIndexOf("def", 25);

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17

slide-18
SLIDE 18

18 MI KE

TM approved

Version 2005/2

  • utput += "\nLast \"hello\" is located at index " +

letters.LastIndexOf("hello", 20, 15);

  • utput += "\n\nFirst occurrence of 'c', 'a', '$' is " + "located at " +

letters.IndexOfAny(searchLetters);

  • utput += "\nFirst occurrence of 'c', 'a' or '$' is " + "located at " +

letters.IndexOfAny(searchLetters, 7);

  • utput += "\nFirst occurrence of 'c', 'a' or '$' is " + "located at " +

letters.IndexOfAny(searchLetters, 20, 5);

  • utput += "\n\nLast occurrence of 'c', 'a' or '$' is " + "located at " +

letters.LastIndexOfAny(searchLetters);

  • utput += "\nLast occurrence of 'c', 'a' or '$' is " + "located at " +

letters.LastIndexOfAny(searchLetters, 1);

  • utput += "\nLast occurrence of 'c', 'a' or '$' is " + "located at " +

letters.LastIndexOfAny(searchLetters, 25, 5); MessageBox.Show(output, "Demonstrating class index methods", MessageBoxButtons.OK, MessageBoxIcon.Information); } // end method Main } // end class StringIndexMethods 18 19 20 21 22 23 24 25 26 27

slide-19
SLIDE 19

19 MI KE

TM approved

Version 2005/2

StringIndexMethods.cs

slide-20
SLIDE 20

20 MI KE

TM approved

Version 2005/2

More String Methods

Method Trim

removes whitespaces at the beginning and

end.

  • riginal string is changed.

Method Replace

changes all occurrences of one char or string

with another one.

  • riginal string remains unchanged.
slide-21
SLIDE 21

21 MI KE

TM approved

Version 2005/2

using System; using System.Windows.Forms; class StringMethods2 { static void Main(string [] args) { string string1 = "cheers!"; string string2 = "GOOD BYE "; string string3 = " spaces "; string output;

  • utput = "string1 = \"" + string1 + "\"\n" + "string2 = \"" +

string2 + "\"\n" + "string3 = \"" + string3 + "\"";

  • utput += "\n\nReplacing \"e\" with \"E\" in string1: \"" +

string1.Replace('e', 'E') + "\"";

  • utput += "\n\nstring1.ToUpper() = \"" + string1.ToUpper() +

"\"\nstring2.ToLower() = \"" + string2.ToLower() + "\"";

  • utput += "\n\nstring3 after trim = \"" + string3.Trim() + "\"";
  • utput += "\n\nstring1 = \"" + string1.ToString() + "\"";

MessageBox.Show(output, "Demonstrating various string methods", MessageBoxButtons.OK, MessageBoxIcon.Information); } // end method Main } // end class StringMethods2 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16

slide-22
SLIDE 22

22 MI KE

TM approved

Version 2005/2

StringMethods2.cs

slide-23
SLIDE 23

23 MI KE

TM approved

Version 2005/2

Name Spaces

  • The using System; directive as we have seen before,

allows us to use members of the System namespace.

  • Namespaces are C# program elements designed to

help you organize your programs.

They provide assistance in avoiding name clashes

between two sets of code.

Implementing Namespaces in your own code is a good

habit because it is likely to save you from problems later when you want to reuse some of your code.

  • Namespaces don't correspond to file or directory

names.

If naming directories and files to correspond to

namespaces helps you organize your code, then you may do so, but it is not required.

slide-24
SLIDE 24

24 MI KE

TM approved

Version 2005/2

Name Spaces (2)

// Namespace Declaration using System; namespace csharp_station {

// nested namespace

namespace tutorial { class myExample1 { public static void myPrint1() { Console.WriteLine("First Example

  • f calling another namespace member.");

} } } // Program start class class NamespaceCalling { // Main begins program execution. public static void Main() {

// Write to console

tutorial.myExample1.myPrint1(); tutorial.myExample2.myPrint2(); }

} } // code from the next page follows…

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23

  • A fully qualified name (line 19-20) contains

language element from the namespace name down to the method call.

  • At the top of the listing there is a nested namespace tutorial within the csharp-station namespace

with class myExample1 and method myPrint1.

  • Main() calls the fully qualified name of tutorial.myExample1.myPrint1() at line 19.
  • Since Main() and the tutorial namespace are located in the same namespace, using csharp_station

in the fully qualified name is unnecessary.

slide-25
SLIDE 25

25 MI KE

TM approved

Version 2005/2

Name Spaces (3)

24 25 26 27 28 29 30 31 32

  • Here is an addition to the csharp_station.tutorial namespace.
  • The classes myExample1 and myExample2 both belong to the same namespace.
  • Additionally, they could be written in separate files and still belong to the same namespace.
  • In Main() line 20, the myPrint2() method is called with the fully qualified name

tutorial.myExample2.myPrint2().

  • Although the class myExample2 is outside the bounding braces of where the method myPrint2 is called, the

namespace csharp_station does not need to be a part of the fully qualified name. This is because both classes belong to the same namespace, csharp_station.

  • Notice that we used different names for the two classes myExample1 and myExample2. This was necessary

because every namespace member of the same type must have a unique name.

// same namespace as nested previous namespace namespace csharp_station.tutorial { class myExample2 { public static void myPrint2() { Console.WriteLine("Second Example of calling another namespace member."); } } }

slide-26
SLIDE 26

26 MI KE

TM approved

Version 2005/2

Name Spaces (4)

// Namespace Declaration using System; using csTut = csharp_station.tutorial.myExample; // Program start class class AliasDirective { // Main begins program execution. public static void Main() { // Call namespace member csTut.myPrint(); myPrint(); } // Potentially ambiguous method. static void myPrint() { Console.WriteLine("Not a member of csharp_station.tutorial.myExample."); } } // C# Station Tutorial Namespace namespace csharp_station.tutorial { class myExample { public static void myPrint() { Console.WriteLine("This is a member of csharp_station. tutorial.myExample."); } } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31

slide-27
SLIDE 27

27 MI KE

TM approved

Version 2005/2

Enums

  • Enums are strongly typed constants. They are essentially

unique types that allow you to assign symbolic names to integral values.

  • In the C# tradition, they are strongly typed, meaning

that an enum of one type may not be implicitly assigned to an enum of another type even though the underlying value

  • f their members are the same.

Along the same lines, integral types and enums are not

implicitly interchangable.

All assignments between different enum types and integral

types require an explicit cast.

  • Enums lend themselves to more maintainable code

because they are symbolic, allowing you to work with integral values, but using a meaningful name to do so.

For example, what type of code would you rather work with -

a set of values named North, South, East, and West or the set

  • f integers 0, 1, 2, and 3 that mapped to the same values,

respectively.

Enums make working with strongly typed constants via

symbolic names easy.

slide-28
SLIDE 28

28 MI KE

TM approved

Version 2005/2

Enums (2)

  • Enums are value types, which means they contain their
  • wn value, can't inherit or be inherited from, and

assignment copies the value of one enum to another.

  • We will see later that enums are used and referred to

with both lower case, enum , and upper case, Enum .

  • Strangely enough, the relationship between the two is

that the C# type, enum, inherits the Base Class Library (BCL) type, Enum. Use the C# type, enum, to define new enums and use the BCL type, Enum, to implement static enum methods.

  • Whenever there are situations where you are using a

set of related numbers in a program, consider replacing those numbers with enums. It will make a program more readable and type safe.

slide-29
SLIDE 29

29 MI KE

TM approved

Version 2005/2

Enums (3)

public enum Volume { Low, Medium, High } class EnumSwitch { static void Main() { Volume myVolume = Volume.Medium; switch (myVolume) { case Volume.Low : Console.WriteLine("The volume has been turned Down."); break; case Volume.Medium : Console.WriteLine("The volume is in the middle."); break; case Volume.High : Console.WriteLine("The volume has been turned up."); break; } Console.ReadLine(); } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22

slide-30
SLIDE 30

30 MI KE

TM approved

Version 2005/2

Enums (4)

  • Notice that it is declared with the enum keyword, has a type

identifier (Volume), and contains a comma separated list of values enclosed within curly braces.

  • This enum is of type Volume and we use it to declare the

myVolume variable in the Main method. Since an enum is a value type, we can assign a value (Volume.Medium) to it directly, similar to the simple types such as int or double. Once the myVolume variable is declared and initialized, it is used in the switch statement. Each of the case statements represent a unique member of the Volume enum.

  • Any time a member of the Volume enum is used, it is fully

qualified with the "Volume" identifier to guarantee type

  • safety. For example, if there were a Meat enum in scope,

then Meat.Medium would definitely have different semantics than Volume.Medium. With both enums in scope, it would be ambiguous to just use the Medium identifier without type

  • qualification. Using the type identifier ensures such mistakes

are not made.

slide-31
SLIDE 31

31 MI KE

TM approved

Version 2005/2

Enums (5)

using System; // declares the enum public enum Volume : byte { Low = 1, Medium, High } class EnumBaseAndMembers { static void Main() { // create and initialize // instance of enum type Volume myVolume = Volume.Low; // make decision based // on enum value switch (myVolume) { case Volume.Low: Console.WriteLine("The volume has been turned Down."); break; case Volume.Medium: Console.WriteLine("The volume is in the middle."); break; case Volume.High: Console.WriteLine("The volume has been turned up."); break; } Console.ReadLine(); } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39

slide-32
SLIDE 32

32 MI KE

TM approved

Version 2005/2

Enums (6)

  • The base type is changed to byte with the : < type>

syntax following the enum identifier, Volume. This ensures that the Volume enum may only have members with values that are valid for type byte.

  • The first member of the Volume enum, Low, has its

value changed to 1. The same syntax, < member> = <value>, may be applied to any member of the

  • enum. You are restricted from creating forward

references, circular references, and duplicate references in enum members.

  • The default values of the Volume enum are Low=0,

Medium=1, and High=2 because the first member of an enum defaults to 0 and the following members default to one more than their predecessor. However, here the Volume enum has its Low member set to 1, which means that Medium=2 and High=3.

slide-33
SLIDE 33

33 MI KE

TM approved

Version 2005/2

Structs

using System; struct Point { public int x; public int y; public Point(int x, int y) { this.x = x; this.y = y; } public Point Add(Point pt) { Point newPt; newPt.x = x + pt.x; newPt.y = y + pt.y; return newPt; } } /// Example of declaring and using a struct class StructExample { static void Main(string[] args) { Point pt1 = new Point(1, 1); Point pt2 = new Point(2, 2); Point pt3; pt3 = pt1.Add(pt2); Console.WriteLine("pt3: { 0} :{ 1} ", pt3.x, pt3.y); } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26

  • The basic layout of a struct is much like a

class, but with differences.

  • The Point struct has a constructor which

initializes its fields to the x and y values passed in.

  • It also has a method named Add(), which

will accept another Point struct, add it to this struct, and return a new struct.

slide-34
SLIDE 34

34 MI KE

TM approved

Version 2005/2

Structs (2)

  • Notice that there is a Point struct declared in the Add() method.

It does not need to be instantiated with a new operator, like a

class.

When this occurs, the struct is implicitly instantiated with its default

(or parameterless) constructor.

The parameterless constructor initializes all struct fields to default

  • values. i.e. integrals are 0, floating points are 0.0, and booleans are

false.

It's illegal to define a parameterless constructor for a struct.

  • Although not required, a struct may be instantiated with a new
  • perator.

In the previous listing, the pt1 and pt2 Point structs are initialized

with values by using the constructor defined in the Point struct.

A third Point struct, pt3 is declared and defaults to using the

parameterless (default) constructor, because it doesn't matter what it's value is at this point.

The Add() method of the pt1 struct is then invoked, passing the pt2

struct as a parameter. The result is assigned to pt3, showing that a struct may be used just like any other value type.

slide-35
SLIDE 35

35 MI KE

TM approved

Version 2005/2

Exception Handling

  • Exceptions are unforeseen errors that happen in our

programs.

  • Most of the time, we can, and should, detect and

handle program errors in our code.

For example, validating user input, checking for null

  • bjects, and verifying the values returned from methods

are what we expect, are all examples of good standard error handling that we should be doing all the time.

  • However, there are times when we don't know if an

error will occur.

For example, we can't predict when we'll receive a file I/ O

error, run out of system memory, or encounter a database error.

These things are generally unlikely, but they could still

happen and we want to be able to deal with them when they do occur. This is where exception handling comes in.

slide-36
SLIDE 36

36 MI KE

TM approved

Version 2005/2

Exception Handling (2)

When exceptions occur, they are said to be

"thrown".

What is actually thrown is an object that is derived

from the System.Exception class.

The thrown exceptions are handled with try/catch

blocks.

The System.Exception class provides several

methods and properties for obtaining information on what went wrong. For example,

the Message property provides summary information

about what the error was,

the StackTrace property provides information from the

stack for where the problem occurred, and

the ToString() method is overridden to reveal a

verbose description of the entire exception.

slide-37
SLIDE 37

37 MI KE

TM approved

Version 2005/2

Exception Handling (3)

Identifying the exceptions we'll need to handle

depends on the routine we're writing.

For example, if the routine opened a file with the

System.IO.File.OpenRead() method, it could throw any of the following exceptions:

SecurityException ArgumentException ArgumentNullException PathTooLongException DirectoryNotFoundException UnauthorizedAccessException FileNotFoundException NotSupportedException

slide-38
SLIDE 38

38 MI KE

TM approved

Version 2005/2

try/catch Blocks

When exceptions are thrown, you need to be able to

handle them by implementing a try/catch block.

Code that could throw an exception is put in the try block

an exception handling code goes in the catch block.

using System; using System.IO; class TryCatchDemo { static void Main(string[] args) { try { File.OpenRead("NonExistentFile"); } catch(Exception ex) { Console.WriteLine(ex.ToString()); } } } 1 2 3 4 5 6 7 8 9 10 11 12 Although the code

in the this Listing

  • nly has a single

catch block, all exceptions will be caught there because the type is

  • f the base

exception type "Exception".

slide-39
SLIDE 39

39 MI KE

TM approved

Version 2005/2

Exception Handling (4)

  • In exception handling, more specific exceptions will be caught

before their more general parent exceptions.

  • For example, the following code fragment shows how to place

multiple catch blocks:

If the file doesn't exist, a FileNotFoundException exception will be

thrown and caught by the first catch block.

However, if a PathTooLongException exception was raised, the

second catch part would catch the exception. This is because there isn't a catch block for the PathTooLongException exception and the generic Exception type catch block is the only option available to catch the exception.

catch(FileNotFoundException fnfex) { Console.WriteLine(fnfex.ToString()); } catch(Exception ex) { Console.WriteLine(ex.ToString()); }

slide-40
SLIDE 40

40 MI KE

TM approved

Version 2005/2

finally Block

An exception can leave your program in an

inconsistent state by not releasing resources or doing some other type of cleanup.

A catch block is a good place to figure out what

may have went wrong and try to recover, however it can't account for all scenarios.

Sometimes you need to perform clean up

actions whether or not your program

  • succeeds. These situations are good candidates

for using a finally block.

slide-41
SLIDE 41

41 MI KE

TM approved

Version 2005/2

finally Block (2)

using System; using System.IO; class FinallyDemo { static void Main(string[] args) { FileStream outStream = null; FileStream inStream = null; try {

  • utStream = File.OpenWrite(

"DestinationFile.txt"); inStream = File.OpenRead( "BogusInputFile.txt"); } catch(Exception ex) { Console.WriteLine(ex.ToString()); } finally { if (outStream != null) {

  • utStream.Close();

Console.WriteLine( "outStream closed."); } if (inStream != null) { inStream.Close(); Console.WriteLine( "inStream closed."); } } } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34

slide-42
SLIDE 42

42 MI KE

TM approved

Version 2005/2

finally Block (3)

The previous listing illustrates the usefulness of a finally

block.

As we know, a file stream must be closed when your done

with it. In this case, the file stream is the resource that needs to be cleaned up.

  • utStream is opened successfully, meaning the program

now has a handle to an open file resource.

When trying to open the inStream, a FileNotFoundException

exception is raised, causing control to go immediately to the catch block.

It's possible to close the outStream in the catch block, but

what if the algorithm executed successfully without an exception? On success, the file would never be closed.

Fortunately, we've included a finally block, which will

always be executed. That's right, regardless of whether the algorithm in the try block raises an exception or not, the code in the finally block will be executed before control leaves the method.

slide-43
SLIDE 43

43 MI KE

TM approved

Version 2005/2

finally Block (4)

A finally block is not required and you may ask what

happens if you just put code after the catch block.

True, under normal circumstances, if the exception is

caught, all code following the catch will be executed.

However, try/ catch/ finally is for exceptional circumstances

and it is better to plan for the worst to make our program more robust.

For example, if one of the catch handlers re-threw and

exception or caused another exception, the code following the catch block (not in a finally block) would never be executed.

Also, if we don't catch the exception at all, program flow

would immediately do a stack walk looking for an exception handler that fits and the code following the catch blocks would not be executed.

Since there is too much potential for code in an algorithm to

not be executed, a finally block is our insurance for executing those critical actions we need.