Home

Introduction

 

Fundamentals

 

Introduction

 

 

     
 
 

 

   
   
 

Previous Copyright © 2015 FunctionX Next

Home

Exception Handling

 

Fundamentals of Exception Handling

   

Introduction

An error is something that is not part of the regular proceeding of a program. It manifests in various ways:

To help you address such issues, the F# language provides a series of mechanisms referred to as exception handling.

Trying an Exception

In all of the programs we have used so far, we assumed that everything would work alright. In some cases, something would go wrong. In a section of code where something could go wrong, you are asked to try evaluating that section. You start with the try keyword. The part is referred to as the try section and it contains one or more statements:

try
    statement(s)

This is where you process the regular statement.

Handling an Exception

If everything in the try section is alright, the program proceeds regularly. If something goes wrong, you can address the issue in the subsequent section that uses the with keyword. The formula to follow is:

try
    statement(s)
with
    handler

If the statement(s) in  the try section is(are) alright, there is no error and the program proceeds as intended. If something goes wrong, you use the with section to indicate what to do. The with section uses a matching mechanism that has one or more cases. A case can use the following formula:

| option -> handling

There are different ways you can use an option. One of the formulas to use is:

| identifier when condition

An identifier can be any letter or appropriate word. This is followed by the when keyword and a Boolean operation that evalues to true or false. This is followed by -> and what to do. If you don't have any specific way to take care of it, you can just add empty parentheses. Here is an example:

let btnCalculateClick e =
    let mutable number = 1.00
    
    try
        number <- (float txtNumber.Text)
        txtResult.Text <- number.ToString()
    with
        | wrongValue when (number < 0.00) -> ()

As an alternative, you can display a message using a message box, ignoring its return value. Here is an example:

let btnCalculateClick e =
    let mutable number = 1.00
    
    try
        number <- (float txtNumber.Text)
        txtResult.Text <- number.ToString()
    with
        | wrongValue when (number < 0.00) -> MessageBox.Show "The value you provided is not a valid number." |> ignore

Raising an Exception

Somewhere in your program, you can detect where something would go wrong and create an exception. This is referred to as raising an exception. This is done using the raise() function. This function takes one argument that can be a string. To start, somewhere before addressing the exception, create a line of code using the exception keyword and the following formula:

exception function-name of parameter(s)

Start with the exception keyword followed by a name that will be used as a function. The name is followed by the of keyword followed by a type. We will come back to the issue.

In the section of code where a statement is evaluated, create a conditional statement that finds out if there is an error, in which case, call the raise() function to which you pass the function-name with, if necessary, its argument(s).

In the with section, call the  function-name as a case.

Concerning the  function-name:

Raising Many Exceptions

In the try section, you can raise as many exceptions as you want. One option is to use various conditional statements to raise each exception. In this case, in the with section, create a match for each option. To start, you can create the appropriate exception function for each case. Here is one example:

open System
open System.Drawing
open System.Windows.Forms 

let exercise = new Form()
exercise.Text <- "Exercise";
exercise.MaximizeBox <- false
exercise.ClientSize <- new System.Drawing.Size(180, 115)
exercise.StartPosition <- FormStartPosition.CenterScreen;

// Label: Number
let lblNumber = new Label()
lblNumber.AutoSize <- true
lblNumber.Text <- "Number:"
lblNumber.Location <- new Point(23, 20)
exercise.Controls.Add lblNumber

// Text Box: Number
let txtNumber = new TextBox()
txtNumber.Location <- new Point(76, 17)
txtNumber.Size <- new System.Drawing.Size(75, 20)
txtNumber.TextAlign <- HorizontalAlignment.Right
exercise.Controls.Add(txtNumber)

// Button: Calculate
let btnCalculate = new Button()
btnCalculate.Text <- "Calculate"
btnCalculate.Location <- new Point(76, 43)
btnCalculate.Size <- new System.Drawing.Size(75, 23)
exercise.Controls.Add btnCalculate

// Label: Result
let lblResult = new Label()
lblResult.AutoSize <- true
lblResult.Text <- "Result:"
lblResult.Location <- new Point(23, 75)
exercise.Controls.Add lblResult

// Text Box: Result 
let txtResult = new TextBox()
txtResult.TextAlign <- HorizontalAlignment.Right
txtResult.Size <- new System.Drawing.Size(75, 23)
txtResult.Location <- new Point(76, 72)
exercise.Controls.Add txtResult

exception GetErrorType of unit
exception ShowMessage of string
exception IdentifyValue of string * double

let btnCalculateClick e =
    let mutable number = 0.00
    let mutable result = 0.00
    
    try
        if txtNumber.Text = "" then
            raise (GetErrorType())
        elif txtNumber.Text = "0.00" then
            raise (ShowMessage("0.00 is not allowed."))
        
        number <- float txtNumber.Text
        
        if number < 0.00 then
            raise (IdentifyValue("The values you provided is not valid:", number))
        
        result <- number * 2.00
        txtResult.Text <- number.ToString()
    with
        | GetErrorType() -> MessageBox.Show "The value you provided could not be evaluated." |> ignore
        | ShowMessage(msg) -> MessageBox.Show (sprintf "%s" msg) |> ignore
        | IdentifyValue(str, value) -> MessageBox.Show (sprintf "%s %f" str value) |> ignore
        | _ -> ()

btnCalculate.Click.Add btnCalculateClick

[<EntryPoint>]
let main argv = 
    Application.Run exercise
    0

Here are example of executing the program:

Raising Many Exceptions


Raising Many Exceptions


Raising Many Exceptions


Raising Many Exceptions

Introduction to Exception Handling.NET

 

Introduction

Before the creation of the .NET Framework, many computer languages supported error or exception handling. These included C++ (with its try . . . catch(...) mechanism, Visual Basic (with its On Error GoTo ... mechanism). This means that different languages used different techniques to address the issues related to errors. As those languages were adapted to the .NET Framework, a unified technique was created. As a result, all languages of the .NET Framework must support exception handling and they practically use the same technique. To start, the .NET Framework includes various classes purposely made for exception handling.

The Exception Class

The most fundamental class that supports exception handling in the .NET Framework is called Exception. The class starts as follows:

type Exception =  
    class
    	abstract Message : string with get 
	override Message : string with get
	abstract Source : string with get, set 
	override Source : string with get, set
	abstract Data : IDictionary with get 
	override Data : IDictionary with get

	. . .

        interface ISerializable 
        interface _Exception 
    end

The Source property indicates what caused the error. The source can be anything. It depends on the type of error and what was going on. One of the most important characteristics of the Exception class is a property named Message. Like the name indicates, this property holds a description of the error that was produced.

In reality, both the source and the message from the Exception class are vague and could mean anything in different circumstances. In reality, when handling an exception in your program, you are free to indicate the source of the problem and to provide a message to display. To let you get more information about the error, the Exception class is equipped with a property named Data.

As mentioned above, the Exception class is vague. It mostly serves as a foundation for other classes. In fact, if you want to create a customized way to handle exceptions in your program, you can create a class that derives from Exeption.

Other Exception Classes

Instead of creating your own classes to handle exceptions, the .NET Framework provides many good classes for various situations. There are classes to address issues related to numbers, files, pictures, music, databases, etc. Some of the most regularly used classes are:

To use the .NET Framework exception handling, use the :? operator as the option the with section. The operator is followed by the name of the class you want to use, the as keyword, the name of the parameter, and ->. Then handle the exception. Here is an example:

open System
open System.Drawing
open System.Windows.Forms 

let exercise = new Form()
exercise.Text <- "Exercise"
exercise.MaximizeBox <- false
exercise.ClientSize <- new System.Drawing.Size(180, 115)
exercise.StartPosition <- FormStartPosition.CenterScreen

// Label: Number
let lblNumber = new Label()
lblNumber.AutoSize <- true
lblNumber.Text <- "Number:"
lblNumber.Location <- new Point(23, 20)
exercise.Controls.Add lblNumber

// Text Box: Number
let txtNumber = new TextBox()
txtNumber.Location <- new Point(76, 17)
txtNumber.Size <- new System.Drawing.Size(75, 20)
txtNumber.TextAlign <- HorizontalAlignment.Right
exercise.Controls.Add(txtNumber)

// Button: Calculate
let btnCalculate = new Button()
btnCalculate.Text <- "Calculate"
btnCalculate.Location <- new Point(76, 43)
btnCalculate.Size <- new System.Drawing.Size(75, 23)
exercise.Controls.Add btnCalculate

// Label: Result
let lblResult = new Label()
lblResult.AutoSize <- true
lblResult.Text <- "Result:"
lblResult.Location <- new Point(23, 75)
exercise.Controls.Add lblResult

// Text Box: Result 
let txtResult = new TextBox()
txtResult.TextAlign <- HorizontalAlignment.Right
txtResult.Size <- new System.Drawing.Size(75, 23)
txtResult.Location <- new Point(76, 72)
exercise.Controls.Add txtResult

let btnCalculateClick e =
    let mutable number = 0.00
    let mutable result = 0.00
    
    try
        number <- float txtNumber.Text
        
        result <- number * 2.00
        txtResult.Text <- result.ToString()
    with
    | :? FormatException as exc -> MessageBox.Show("You provided an invalid number", "Algebra",
                                          MessageBoxButtons.OK, MessageBoxIcon.Information) |> ignore;

btnCalculate.Click.Add btnCalculateClick

[<EntryPoint>]
let main argv = 
    Application.Run exercise
    0

Here is an example of executing the program:

Other Exception Classes

Resources Cleaning Up

 

Introduction

Some applications or parts of an application use a lot of resources. Examples of resources are hard drives, servers, communication media, etc. For example, an application may be asked to locate and use files on a computer. Another application may have to create a connection to a database on a remote computer. Sometimes, these types of operations require that an application monopolyze a resource and other applications must wait. For example, while one application opens and is using a file, other applications may be prevented from using or accessing that same file. When the first application has finished using the resource, it must stop using the resource so that other applications that need the same resource can use it. To help you take care of this, the F# language provides the finally keyword. The formula to use it is:

try
    statement(s)
finally
    body

You start with a try section exactly as we reviewed for the regular exception handling. In the finally section, create the code that would free the resources. Normally, the finally section is not used for regular exception handling; it is used to free resources that were used in a program. If you want to handle an exception, create the appropriate with section in the try block. The formula to follow is:

try
    try
        statement(s)
    with
        exception-handler
finally
    body

Cleaning-Up After Using a Resource

The finally option requires a few steps that include an explicit free-up of resources after using them. The .NET Framework provides a better mechanism through an interface named IDispose. This interface has only one method named Dispose. This method takes no argument and returns nothing. The actual role of this method is to clean-up resources that an application was using.

To apply this mechanism, you must use a class that implements the IDispose interface. Of course, you can create your own class that implements this interface. In reality, all of the classes used in scenarios that consume resources implement the IDispose interface. When using one of those classes, to assist you with freeing the resources, the F# language provides the use keyword that is used as an operator. The formula to use it is as follows:

use variable = method

The use keyword is followed by a variable of the class that will be used to consume resources. On the right side of =, call a method that will be used to actually consume the resources. When the method has finished doing its work, the compiler calls the IDispose.Dispose() method to free the resources that were used. An alternative is the one used by other languages. This technique uses the using() function. The formula to use it is:

using(Parameter) body

The using() function takes one argument that specifies what method will consume resources. The body of this function follows the = sign. If the body is short enough, it can be written on the same line that calls the using() function. If the body involves many lines, it should be created on the next line. In this case, the body should be indented. At the end of the body of the function, the compiler calls the IDispose.Dispose() method to free the resources that were used.


Home Copyright © 2014-2015, FunctionX Home