Exception

Exception คือคุณสมบัติในภาษา Visual Basic ที่ให้คุณสามารถจัดการกับข้อผิดพลาดที่ไม่คาดฝันที่อาจจะเกิดขึ้นในขณะที่โปรแกรมกำลังทำงาน โดยการทำงานของ Exception นั้นจะช่วยให้โปรแกรมไม่ Error หรือหยุดการทำงานเมื่อเกิดข้อผิดพลาดขึ้น

ในการจัดการ Exception จะใช้คำสั่ง Try สำหรับตรวจจับข้อผิดพลาด คำสั่ง Catch สำหรับจัดการกับข้อผิดพลาดที่เกิดขึ้น ซึ่งการทำงานก็คือเมื่อเกิดขึ้น Exception ขึ้นในบล็อคของคำสั่ง Try โปรแกรมจะหยุดการทำงานในบล็อคนั้นทันทีและข้ามไปทำงานในบล็อคคำสั่ง Catch แทน ต่อไปเป็นรูปแบบการตรวจจับ Exception ในภาษา Visual Basic

Try
    ...
Catch ex As ExceptionType
    ...
End Try

จากรูปแบบการใช้งาน Exception ในบล็อคของคำสั่ง Try เป็นส่วนในการตรวจจับ Exception ที่อาจจะเกิดขึ้น ในบล็อคของคำสั่ง Catch เป็นการจัดการกับ Exception โดย ExceptionType เป็นประเภทของ Exception โดยบล็อคของคำสั่ง Catch สามารถมีได้หลายบล็อคถ้าหากมีมากกว่าหนึ่ง Exception ที่สามารถเกิดขึ้นได้

การตรวจจับและจัดการ Exception

ต่อไปมาดูตัวอย่างการตรวจจับ Exception ในภาษา Visual Basic เราจะให้ตัวอย่างสำหรับการหารตัวเลข Integer สองจำนวน และเราจะจัดการกับ Exception ที่อาจจะเกิดขึ้น

Module ExcepetionExample

    Sub Main()

        Dim a As Integer = 10
        Dim b As Integer = 0

        Try
            Dim c As Integer = a \ b
        Catch ex As DivideByZeroException
            Console.WriteLine(ex.Message)
        End Try

    End Sub

End Module

ในตัวอย่างเป็นโปรแกรมในการหารตัวเลขสองตัว โดยในบล็อคของคำสั่ง Try นั้น Exception สามารถเกิดขึ้นได้ถ้าหาก ค่าของ b เป็น 0 เมื่อเรารันโปรแกรมนี้จะทำให้เกิด Exception ขึ้นโดย common language runtime (CLR) ดังนั้นเราจึงต้องตรวจจับ DivideByZeroExceptionException ซึ่งเป็นคลาสจากไลบรารี่ ในภาษา Visual Basic

Attempted to divide by zero.

นี่เป็นผลลัพธ์ของโปรแกรม คุณจะเห็นว่าโปรแกรมจะทำงานในบล็อคคำสั่ง Catch ที่เราได้แสดงข้อความเกี่ยวกับ Exception จาก Property ex.Message ถ้าคุณเปลี่ยนค่า b เป็นค่าอื่นที่ไม่ใช้ 0 Exception จะไม่เกิด

การจัดการกับหลาย Exception

ในการทำงานบางอย่างนั้นอาจจะสามารถเกิด Exception ได้หลายแบบในคำสั่งเดียวหรือหลายคำสั่ง ดังนั้นคุณสามารถตรวจจับหลาย Exception ได้โดยการเพิ่มบล็อคของคำสั่ง Catch เข้าไปสำหรับจัดการกับ Exception ได้เท่าที่ต้องการ

Module MultipleExcepetion

    Sub Main()

        Dim names = New String() {"C++", "C#", "Java", "Visual Basic"}
        Dim index As Integer

        Try
            index = CType(Console.ReadLine(), Integer)
            Console.WriteLine(names(index))
        Catch ex As InvalidCastException
            Console.WriteLine(ex.Message)
        Catch ex As IndexOutOfRangeException
            Console.WriteLine(ex.Message)
        End Try

    End Sub

End Module

ในตัวอย่างเป็นการตรวจจับหลาย Exception ในภาษา Visual Basic เราได้เขียนโปรแกรมสำหรับอ่านค่าในอาเรย์ โดยใส่ Index ของอาเรย์เข้ามา ในบล็อคของคำสั่ง Try มีสอง Exception ที่สามารถจะเกิดขึ้นได้สองแบบในโปรแกรมของเรา

index = CType(Console.ReadLine(), Integer)

เรารับค่าเป็น String ก่อนที่จะแปลงเป็นตัวเลขดังนั้นการแปลงอาจจะทำให้เกิด InvalidCastException Exception ขึ้นถ้า หากค่าที่ใส่มาไม่ถูกต้องในรูปแบบของตัวเลข

Console.WriteLine(names(index))

ในคำสั่งนี้เป็นการอ่านค่าอาเรย์จาก Index ที่ใส่เข้ามา ในกรณีที่ตัวเลขของ Index นั้นมีค่ามากกว่าขนาดของอาเรย์จะทำให้เกิด IndexOutOfRangeException Exception ขึ้น

ซึ่งในบล็อคของคำสั่ง Catch แต่ละบล็อคจะเป็นการจัดการกับ Exception แต่ละแบบที่เกิดขึ้น คุณสามารถดูรายละเอียดของ Exception ได้ในตัวแปรออบเจ็ค ex

จากตัวอย่างเดิม ต่อไปเราจะเปลี่ยนเป็นการตรวจจับ Exception แบบซ้อนกัน (nested)

Module NestedExcepetion

    Sub Main()

        Dim names = New String() {"C++", "C#", "Java", "Visual Basic"}
        Dim index As Integer

        Try
            index = CType(Console.ReadLine(), Integer)
            Try
                Console.WriteLine(names(index))
            Catch ex As IndexOutOfRangeException
                Console.WriteLine(ex.Message)
            End Try

        Catch ex As InvalidCastException
            Console.WriteLine(ex.Message)
        End Try

    End Sub

End Module

ในตัวอย่าง เราได้เปลี่ยนการตรวจจับ Exception เป็นแบบ nested ที่คุณสามารถทำได้เช่นเดียวกันกับคำสั่งเงื่อนไขและวนซ้ำ

a
Conversion from string "a" to type 'Integer' is not valid.

นี่เป็นผลลัพธ์ของโปรแกรมเมื่อเราใส่ค่า index ที่ไม่

ถ้าคุณสามารถตรวจจับ Exception ทั้งหมดที่จะเกิดขึ้นในภาษา Visual Basic ได้ด้วยคำสั่ง Catch ex As Exception เพราะว่า Exception ทั้งหมดนั้นสืบทอดมาจากคลาส Exception

User defined exception

User defined exception คือ Exception ที่คุณสามารถสร้างขึ้นมาจัดการกับ Exception ของคุณเองได้ การสร้าง Exception ต้องสืบทอดจากคลาส Exception เสมอ ต่อไปมาดูตัวอย่างสำหรับการสร้าง Exception แบบกำหนดเองในภาษา Visual Basic

Class NegativeNumberException
    Inherits Exception

    Public Sub New()
        MyBase.New("Negative number exception occurred")
    End Sub

End Class

ในตัวอย่างเราได้สร้าง NegativeNumberException Exception สำหรับข้อผิดพลาดถ้าหากตัวเลขนั้นเป็นจำนวนลบ ในคอนสตรัคเตอร์ของ Exception นี้เราได้เรียกใช้คอนสตรัคเตอร์ของ Base คลาสและกำหนดข้อความแจ้งเตือนให้กับ Exception นี้ผ่าน Base คลาส ตัวอย่างต่อไปเราจะใช้งาน Exception ที่เราสร้างขึ้น

การใช้คำสั่ง Throw

คำสั่ง Throw เป็นคำสั่งที่คุณสามารถสั่งให้เกิด Exception ขึ้นได้ ต่อไปเป็นการใช้คำสั่ง Throw สำหรับการทำให้เกิด Exception ขึ้นในทันที เราจะเขียนโปรแกรมหาค่า Factorial โดยให้ผู้ใช้กรอกค่าตัวเลขที่ต้องการเข้ามา

Class NegativeNumberException
    Inherits Exception

    Public Sub New()
        MyBase.New("Negative number exception occurred")
    End Sub

End Class

Module FacorialProgram

    Function Factorial(ByVal n As Integer) As Integer
        If n = 0 Or n = 1 Then
            Return 1
        Else
            Return n * Factorial(n - 1)
        End If
    End Function

    Sub Main()

        Dim number As Integer

        Console.WriteLine("Factorial program")
        Console.Write("Enter a positive number: ")

        Try
            number = CType(Console.ReadLine(), Integer)
            If number < 0 Then
                Throw New NegativeNumberException()
            End If

            If number > 10 Then
                Throw New OverflowException("Fatorial's result exceeds maximum value that integer type can handle")
            End If

            Console.WriteLine("{0}! = {1}", number, Factorial(number))

        Catch ex As NegativeNumberException
            Console.WriteLine(ex.Message)
        Catch ex As OverflowException
            Console.WriteLine(ex.Message)
        End Try

    End Sub

End Module

ในตัวอย่างเป็นโปรแกรมหาค่า Factorial โดยเราจะนำคลาส NegativeNumberException ที่เราได้สร้างไว้ก่อนหน้ามาใช้งาน และเราจะใช้คำสั่ง Throw สำหรับทำให้เกิด Exception ขึ้น ในการหาค่า Factorial นั้นจะมีเงื่อนไขบางอย่างที่เราต้องตรวจสอบ

If number < 0 Then
    Throw New NegativeNumberException()
End If

ในคำสั่งนี้เราได้ตรวจสอบตัวแปร number ถ้าหากมันมีค่าน้อยกว่า 0 เพราะว่าการหาค่า Factorial สำหรับค่าลบนั้นไม่มี เราจึงทำให้เกิด NegativeNumberException Exception ขึ้น

If number > 10 Then
    Throw New OverflowException("Factorial's result exceeds maximum value that integer type can handle")
End If

ในคำสั่งเราได้ตรวจสอบถ้าหากตัวเลขที่ต้องการหา Factorial นั้นใหญ่กว่า 10 ซึ่งประเภทข้อมูลแบบ Integer ที่เราได้กำหนดไว้ในฟังกชัน Factorial จะไม่สามารถร้องรับได้ โดยปกติโปรแกรมจะ Throw OverflowException อัตโนมัติถ้าหากมันเกิดขึ้น แต่ในตัวอย่างเราได้ใช้คำสั่ง Throw เพื่อทำให้เกิดขึ้นก่อนเพราะเราทราบล่วงหน้า และเปลี่ยนข้อความผิดพลาดเป็นที่เรากำหนดเอง

การใช้งานคำสั่ง Finally

คำสั่ง Finally จะทำงานเสมอไม่ว่าโปรแกรมจะงานในบล็อคของคำสั่ง Try หรือ Catch มันมักจะใช้กับการทำงานบางอย่างที่จำเป็นต้องทำเสมอไม่ว่าจะเกิด Exception ขึ้นหรือไม่ เช่น การเปิดปิดไฟล์ การอ่านค่าจาก Network Steam

Imports System.IO

Module FinallyStatement

    Sub Main()

        Dim path As String = "d:/MyFile.txt"

        Dim sw As StreamWriter

        Try
            sw = File.AppendText(path)
            Dim tw As TextWriter = CType(sw, TextWriter)
            tw.WriteLine("Writing text to the file.")
            tw.Close()
        Catch ex As Exception
            Console.WriteLine(ex.Message)
        Finally
            If sw IsNot Nothing Then
                sw.Close()
            End If
        End Try

    End Sub

End Module

นี่เป็นตัวอย่างของการทำงานกับไฟล์ เราได้ใช้คำสั่ง Finally สำหรับการปิดการทำงานของ File Stream หลังจากเราใช้คำสั่ง sw = File.AppendText(path) ในการเปิดไฟล์ มันจะต้องถูกปิดเสมอไม่ว่ามันจะเปิดสำเร็จหรือไม่ก็ตาม ดังนั้นการเขียนโปรแกรมเกี่ยวกับไฟล์หรือการ Stream คุณจะต้องปิดทุกครั้ง เพื่อให้โปรแกรมอื่นสามารถใช้ได้ต่อไป

ในบทนี้ คุณได้เรียนรู้เกี่ยวกับ Exception ในภาษา Visual Basic ซึ่งเป็นการจัดการข้อผิดพลาดที่จะเกิดขึ้นในโปรแกรม เพื่อทำให้โปรแกรมมีความปลอดภัยมากที่สุด