มีหลายคนสงสัยว่า VB8 หรือ VB.NET 2005 ปรับปรุงอะไรเพิ่มขึ้นบ้างจากเวอร์ชั่นก่อน ผมเลยค้นคว้ามาบอกกันไว้ครับ เผื่อหลายๆ คนต้องเอาไปอธิบายคนที่สงสัยอีกหลายๆ คน
VB.NET 2005 นั้น มาพร้อมกับ .NET 2.0 ซึ่งได้ปรับปรุงตัวแปลภาษาไป 14 ข้อดังนี้
1. เพิ่ม Continue Statement
คำสั่ง Continue จะใช้ร่วมกับคำสั่ง Do, For, While มีประโยชน์ในการจบการวนครั้งปัจจุบัน แล้วไปเริ่มวนครั้งถัดไปเลย ตัวอย่างการใช้งาน
'การใช้ Continue เพื่อทำลูปครั้งถัดไปเลย
Dim Result As Byte = 0
For Count As Byte = 0 To 4
If Count = 2 Then Continue For
Result += Count
Next Count
จากโค้ดด้านบน การทำงานจะผ่านบรรทัด Result += Count เพียง 4 ครั้งเท่านั้น ทำให้ตัวแปร Result สุดท้ายมีค่าเป็น 0 + 1 +3 + 4 = 8 เพราะในรอบที่ 3 คำสั่ง Continue จะทำงาน ซึ่งมีผลให้ทำงาน ที่ Next ถัดไปแทน
2. เพิ่มความสามารถในการเข้าถึง Form แบบ Visual Basic 6
ถ้าใครเคยใช้ VB6 แล้วเปลี่ยนมาใช้ VB.NET 2003 จะพบว่า สิ่งที่ต้องปรับตัวมากที่สุด คือ เรื่อง Object-Oreinted Programming ซึ่งแม้กระทั่ง Form ที่ใช้ ก็ต้องคิดแบบ OO นั้นคือ Form ทุก Form ต้องเป็น Class ดังนั้นจะเรียกใช้ Form ใดๆได้ ก็ต้องสร้าง Instance หรือ Object ของ Form นั้นๆก่อนเสมอ ซึ่งเป็นเรื่องวุ่นวายมากสำหรับคนที่คุ้นเคย VB6
เมื่อมีผู้เรียกร้องเข้ามามาก ว่าความง่ายของ VB หายไปเยอะ ทางผู้พัฒนา VB Compiler จึงนำ concept เดิมมาใช้ นั้นคือ สามารถเข้าถึงหรือเรียกใช้ Form อื่นๆ ได้โดยไม่ต้องสร้าง Object ก่อน ดังตัวอย่างข้างล่าง
จากเดิมใน VB.NET 2003 เมื่อต้องใช้งาน Form อื่นๆ
'Form1 เรียก Form2 จะต้องสร้าง Object ของ Form2 ก่อนเสมอ
Public Class Form1
Dim objForm2 As New Form2
Sub ShowForm2()
objForm5.Show()
End Sub
End Class
เมื่อต้องใช้งาน Form อื่นๆ ใน VB.NET 2005 ก็สามารถงานได้ง่ายๆ (โดยแบบเดิมก็ยังใช้ได้อยู่)
'Form1 เรียก Form2 โดยไม่ต้องสร้าง Object ของ Form2 เลย
Public Class Form1
Sub ShowForm2()
Form2.Show()
End Sub
End Class
3. เพิ่ม IsNot Operator
จากเดิมที่เวลาเปรียบเทียบ ตัวแปรอ็อบเจ็ค ว่าชี้ไปที่ Object เดียวกันรึเปล่า ก็ใช้คำสั่ง Is หรือ Not ... IS ... ซึ่ง syntax อ่านยาก เพราะต้องมานั่งนิเสธ (~) คำตอบอีกที ทางทีมงานเลยออกคำสั่ง IsNot มาให้ใช้อีกตัว เพื่อทำให้โค้ดอ่านง่ายขึ้น เช่น
'Object1 และ Object2 มาจาก Class เดียวกัน แต่ชี้ไปคนละ Instance
Dim Object1, Object2 As New Object
'ทั้ง 2 บรรทัดข้างล่างนี้ มีความหมายเหมือนกัน
If Not (Object1 Is Object2) Then MsgฺBox("ทั้ง 2 ตัวแปร ไม่ได้ชี้ไปที่อ็อบเจ็คเดียวกัน")
If Object1 IsNot Object2 Then MsgฺBox("ทั้ง 2 ตัวแปร ไม่ได้ชี้ไปที่อ็อบเจ็คเดียวกัน")
4. เพิ่ม TryCast Operator
คำสั่งในการแปลงชนิดข้อมูล (Type Convertion) ในรุ่นก่อน มีอยู่ 2 คำสั่ง คือ CType และ DirectCast ซึ่งทั้ง 2 คำสั่ง เมื่อไม่สามารถแปลงชนิดข้อมูลได้ จะต้องดักข้อผิดพลาดขึ้นด้วยคลาส InvalidCastException แต่สำหรับคำสั่ง TryCast นั้น เมื่อไม่สามารถแปลงชินดข้อมูลได้ คำสังจะ return ค่าออกมาเป็น Nothing เช่น
ในรุ่นก่อนจะมีเพียงคำสั่ง CType และ DirectCast
'กรณีตัวอย่างการใช้ CType และ DirectCast และเปรียบเทียบความแตกต่าง
Try
Dim x As Object = 1.23
Dim y As Integer = CTpye(x, Interger)
'จะมีข้อผิดพลาด(Fails) ในบรรทัดนี้ เพราะในขณะ run-time นั้น x จะมี type เป็น Double
'และการใช้คำสั่ง DirectCast นั้น ชนิดข้อมูลทั้ง 2 ต้องมีความสัมพันธ์แบบ Inheritance กัน
'ซึ่ง Double และ Integer ก็ไม่ได้สืบทอดกันมา
Dim z As Integer = DirectCast(x, Integer)
Catch ex As InvalidCastException
MessageBox.Show("Casting error")
End Try
ตัวอย่างการตรวจสอบ type ก่อน convert และใช้ DirectCast ในการ casting
Dim obj As Object
Dim PrintableObject As IPrintable
If TypeOf obj Is IPrintable Then
PrintableObject = DirectCast(obj, IPrintable)
PrintableObject.Print()
End If
ตัวอย่างคำสั่ง TryCast ที่เป็นการตรวจสอบ type และ convert ให้คำสังเดียว
'กรณีใช้ TryCast จะคล้ายกับคำสั่ง DirectCast เพราะคำสั่งจะ return Nothing
'เมื่อทั้งสองชนิดไม่ได้มีความสัมพันธ์แบบ Inheritance กัน
Dim x As Double = 1.23
Dim y As Object = TryCast(x, Integer)
If y Is Nothing Then
MessageBox.Show("Cannot casting")
End If
(มีฝรั่งบางคนท้วง การตั้ง Keyword การเปลงชนิดข้อมูลของทั้งสามตัวนี้ว่า ไม่คล้องจองกัน คือ CType, DirectCast, TryCast น่าจะตั้งชื่อเป็น Cast, DirectCast, TryCast มากกว่า มันถึงจะลงท้ายด้วย Cast เหมือนกัน ซึงจำง่ายกว่า)
5. เพิ่ม Using Statement
คำสั่งนี้มีประโยชน์มาก สำหรับผู้ที่ต้องใช้งาน unmaged resource อื่นๆ เช่น File, COM wrapper, SQL Connection ซึ่งการใช้คำสั่ง Using ... End Using จะมีการคืนทรัพยากร (dispose) ให้อัตโนมัติ ซึ่งในรุ่นก่อนจำเป็นต้องใช้ คำสั่ง Try ... End Try เพื่อคืนทรัพยากรให้ระบบ ลองดูตัวอย่างข้างล่างนี้
ตัวอย่าง การคืนทรัพยากรระบบโดยใช้ Try
'ทรัพยากรจะถูกคืนให้ระบบ หลัง Finally Statement
Try
Dim fs As New System.IO.StreamReader("C:\boot.ini")
Console.Write(fs.ReadToEnd)
Catch ex As Exception
Console.Write(ex.message)
Finally
fs.Close()
fs.Dispose()
End Try
ถ้าเปลี่ยนมาใช้ Using ก็จะสะดวกขึ้นมาก
'คำสั่ง Using จะคืนทรัพยากรให้ระบบ เมื่อจบ End Using
Using fs As New System.IO.StreamReader("C:\boot.ini")
Console.Write(fs.ReadToEnd)
End Using
6. เพิ่มวิธีการประกาศ index ของ array โดยระบุ 0 เป็น index เริ่มต้น
ปกติ array ใน VB.NET จะเริ่มจาก 0 อยู่แล้ว แต่เพื่อให้โค้ดอ่านง่ายขึ้น โดยเฉพาะคนที่มาจาก VB6 ซึ่งจะเพิ่มส่วนที่มีการบอกไว้ว่า index ของ array นั้นเริ่มที่ 0 เช่น
Dim Num(0 To 9) As Interger
ก็มีความหมายเดียวกับ
Dim Num(9) As Interger
7. Properties (Get, Set) สามารถกำหนด Access Level ต่างกันได้
เดิมทีนั้น Method Get, Set Access Level จะเหมือนกันโดยปริยาย แต่ใน 2005 สามารถให้ Get และ Set มี Access Level คนละอย่างกันได้ ดังตัวอย่าง
'คลาสนี้จะอนุญาตให้คลาสอื่นที่สืบทอดไป สามารถอ่านค่า salaryValue ได้
'แต่การเขียนจะอนุญาตเฉพาะภายในคลาสตัวเองเท่านั้น
Public Class employee
Private salaryValue As Double
Protected Property salary() As Double
Get
Return salaryValue
End Get
Private Set(ByVal value As Double)
salaryValue = value
End Set
End Property
End Class
8. เพิ่มชนิดข้อมูล 3 Unsigned และ 1 Signed
VB.NET 2005 เพิ่ม Data Type แบบจำนวนเต็ม ที่ไม่มีเครื่องหมาย +,- มาเกี่ยวข้อง หรือพูดง่ายๆ ว่า เป็นค่าบวกอย่างเดียว ได้แก่ UShort, UInteger, ULong และเพิ่ม SByte ที่มีเครื่องหมาย +/- ด้วย รายละเอียดดังนี้
UShort มีขนาด 16 bits (2 bytes) เก็บค่าได้ตั้งแต่ 0 ถึง 65,535
UInterger มีขนาด 32 bits (4 bytes) เก็บค่าได้ตั้งแต่ 0 ถึง 4,294,967,295
ULong มีขนาด 64 bits (8 bytes) เก็บค่าได้ตั้งแต่ 0 ถึง 18,446,744,073,709,551,615
SByte มีขนาด 8 bits (1 bytes) เก็บค่าได้ตั้งแต่ -127 ถึง 128
9. เพิ่มชนิดข้อมูล Nullable
ปกติในตัวแปรแบบ Value Type จะเก็บค่าใดค่าหนึ่งตามชนิดข้อมูล แม้จะไม่ได้ใส่ค่าใดๆ ไป ค่าในตัวแปรก็จะมีค่าโดย Default อยู่แล้ว แต่ใน VB.NET 2005 ได้เพิ่มความสามารถให้ตัวแปรไม่มีค่าเริ่มต้น หรือไม่เก็บค่าใดๆ เลยก็ได้ ด้วยคำสั่ง Nullable เช่น
'การประกาศให้ตัวแปรไม่เก็บค่าใดๆ
Dim Number As Nullable(Of Integer)
Number = 20
'กำหนดให้ตัวแปร Number ไม่มีค่าใดๆ
Number = Nothing
'ตรวจสอบค่าในตัวแปร Number ใช้ property ชื่อ HasValue (ไม่สามารถใช้ Is Nothing ในการตรวจสอบได้)
If Number.HasValue Then
MsgBox("Value is " & Number.Value)
Else
MsgBox("No Value")
End If
์ี10. เพิ่มความสามารถในการทำ Operator Overloading
แม้จะไม่มีสถานะการณ์ที่ต้องให้ใช้ Operator Overloading บ่อยๆ แต่มันก็เป็นความสามารถด้าน OO ที่ Advance และมีประโยชน์มาก เพราะบางครั้งเราก็ต้องการใช้ Operator ที่มีอยู่ในความหมายอื่นๆ หรือใช้กับ operands ที่เป็นอ็อบเจ็คอื่นๆ เช่น operator + ปกติแล้วจะใช้กับ operands 2 ตัว ที่เป็นตัวเลข (primitive type) หรืออ็อบเจ็คตัวเลข (reference type) เท่านั้น อันหมายถึงการเอาค่าตัวเลข 2 ตัว มาบวกกัน แต่ถ้าต้องการใช้กับอ็อบเจ็คอื่นๆ ก็ต้อง overload มาปรับแต่งเอง เช่น
ต้องการ overload ตัว operator เครื่องหมาย + เพื่อให้สามารถรวมค่าความยาวของอ็อบเจ็คดินสอได้
'สร้างคลาสดินสอ ที่มีการใช้ Overload เครื่องหมาย + ไว้
Public Class Pencil
Private Length As Integer
Public Sub New(ByVal Length As Integer)
Me.Length = Length
End Sub
Public Overrides Function ToString() As String
Return Length.ToString()
End Function
Public Shared Operator +(ByVal PencilA As Pencil, _
ByVal PencilB As Pencil) As Integer
Return PencilA.Length + PencilB.Length
End Operator
End Class
'สร้างอ็อบเจ็คดินสอ แล้วใช้ operator + จะไม่เกิด error เพราะมีการกำหนดให้ + ใช้ได้กับคลาสนี้แล้ว
'สมมติความยาวดินสอมีหน่วยเป็น เซนติเมตร
Public Shared Sub Main()
Dim PencilA As New Pencil(10)
Dim PencilB As New Pencil(12)
Dim TwoPencilLength As Integer = PencilA + PencilB
Console.WriteLine("รวมความยาวของดินสอ 2 แท่ง เท่ากับ " & _
TwoPencilLength .ToString() & " เซนติเมตร.")
End Sub
ตัวอย่างนี้แสดงให้เห็นถึงการ Overload เครื่องหมาย + มาใช้กับอ็อบเจ็คอื่นๆ ซึ่งที่จริงสามารถดัดแปลง Operator + ไปในความหมายอื่นๆ ก็ได้ เช่น เอาไปเปรียบเทียบหาดินสอที่ยาวที่สุด เป็นต้น
11. เพิ่มความสามารถในการแบ่งโค้ดออกเป็นส่วนๆ โดยใช้ Partial Types
ตัวอย่างที่เห็นได้ชัด คือ การสร้าง Form ใน Visual Studio.NET 2005 เพราะมีการ generate โค้ดแบบ Partial ทำให้เกิดไฟล์ขึ้น 2 ไฟล์ คือไฟล์ xxx.Designer.vb ที่มีการแยกรายละเอียดของการจัดการ Control ต่างๆ และไฟล์ xxx.vb ที่มีเพียง Class...End Class ซึ่งรอการเพิ่ม event procedure และส่วนที่เราต้องเพิ่มเติมลงไป และยังซ่อน xxx.Designer.vb ไว้ข้างหลัง xxx.vb อีกด้วย การแบ่งโค้ดแบบนี้ช่วยโปรแกรมเมอร์มือใหม่ ไม่ต้องเห็นโค้ดที่ยังไม่เข้าใจ และช่วยลดโค้ดที่ไม่ใช่จุดประสงค์หลักของโปรแกรมออกไป (แต่ผมคิดว่าข้อเสียของการทำ Partial คือ ต้องการการจัดการไฟล์เพิ่มขึ้น ซึ่งคงจะยุ่งยากมากขึ้นสำหรับคนที่ใช้ Partial บน IDE ที่ไม่ได้มีการจัดการเรื่องนี้ดีพอ) ตัวอย่างโค้ดคงจะเห็นบ่อยๆ ในผู้ที่ใช้ Visual Studio.NET 2005 แล้ว ผมเลยจะให้ดูโค้ดสั้นๆ ที่ไม่ได้ถูก generate ขึ้นมา
จากคลาสรูปแบบทั่วไป
'ไฟล์ Man.vb
Public Class Man
Sub Walk()
....
End Sub
Sub Run()
....
End Sub
End Class
เมื่อนำมาเขียนแบบ Partial จะต้องเก็บโค้ดไว้เป็น 2 ไฟล์ ซึ่งควรตั้งชื่อไฟล์ให้สอดคลองกันตามวัตถุประสงค์ เพื่อให้ง่ายต่อการ maintain ภายหลัง
'ไฟล์ ManWalk.vb
Partial Public Class Man
Sub Walk()
....
End Sub
End Class
'ไฟล์ ManRun.vb
Partial Public Class Man
Sub Run()
....
End Sub
End Class
12. เพิ่ม Generic Types
เป็นความสามารถด้าน OOP ชั้นสูงอีกตัวที่พูดถึงกันมาก แม้กระทั้ง Java 1.5 ก็ยัง implement ตัว Generic นี้ลงไปด้วย (รวมทั้งเพิ่ง implement เรื่อง enum ที่มีใน VB6 มากนานมากแล้ว) การใช้งาน Generic จะใช้ตรงส่วน Parameter ของ Class, Structure, Interface, Procedure หรือ Delegate ก็ได้ มีประโยชน์ในการกำหนดให้ parameter เป็น data type ที่หลากหลายได้ พูดไปก็คงนึกภาพไม่ออกครับ ต้องลองดูโค้ดเลย
กำหนดคลาสให้มีการใช้ Generic
'คลาสนกแก้ว
Public Class Parrot(Of T)
Sub Speak(ByVal Word As T)
MsgBox(Word.ToString)
End Sub
End Class
การใช้งานคลาสที่เป็น Generic จะพบว่า parameter สามารถเป็น data type ได้หลายแบบ ดังตัวอย่างข้างล่าง ที่เป็นได้ทั้ง Integer หรือ String
'การสร้างอ็อบเจ็คนกแก้ว แล้วให้พูดเลข 3
Dim objParrot As New Parrot(Of Integer)
objParrot.Speak(3)
'การสร้างอ็อบเจ็คนกแก้ว แล้วให้พูดว่า Hello
Dim objParrot As New Parrot(Of String)
objParrot.Speak("Hello")
13. สามารถปรับแต่ง Event ได้ ด้วยคีเวิร์ด Custom
เป็นความสามารถที่ไม่มีใน C# ที่ชาว VB สามารถนำไปโม้ได้ ซึ่งเหนือกว่าด้วยการลองทำ serialize object ดู พบว่าโค้ด Event ยาวกว่า แต่โค้ดสั้นกว่าและใช้ง่ายกว่าเวลานำไปใช้ อ่านเพิ่มเติมที่ .NET 2.0 solution to serialization of objects that raise events และ Better version of the .NET 2.0 event/serialization solution ประโยชน์ของการปรับแต่ง Event คือ การเพิ่มเหตุกาณ์หรือ trigger ให้กับ object ได้ ตามต้องการ ถ้า object นั้นไม่มี Event ที่ต้องการ โครงสร้าง Custom Event เป็นดังนี้
Public Custom Event .... As EventHandler
AddHandler(ByVal value As EventHandler)
...
End AddHandler
RemoveHandler(ByVal value As EventHandler)
...
End RemoveHandler
RaiseEvent(ByVal sender As Object, ByVal e As EventArgs)
...
End RaiseEvent
End Event
AddHandler จะเป็นที่ใส่คำสั่งต่างๆ เมื่อ add event ให้ object
RemoveHandler จะเป็นที่ใส่คำสั่งต่างๆ เมื่อ remove event จาก object
RaiseEvent จะเป็นที่ใส่คำสั่งต่างๆ เมื่อมีการ trig event จาก object
14. เพิ่ม parameter การแจ้งเตือน ในการทำงานของ Compiler
เป็น option ของ compiler ในการแจ้ง warning ซึ่งเพิ่มขึ้นมา 2 option คือ /nowarn หมายถึง ไม่ต้องแจ้ง warning ใดๆ เลย และ /warnaserror หมายถึง ให้แจ้ง warning เหมือนเป็น error เลย ทั้ง 2 option นี้ ถ้าใช้ VS.NET 2005 สามารถเซตได้ที่คลิ๊กขวาที่ project เลือก properties ข้างล่างสุด แล้วไปที่ menu ชื่อ compile จะพบ checkbox 2 ตัว ที่ชื่อ Disable All Warnings ก็คือ /nowarn และ Treat All Warnings as Errors ก็คือ /warnaserror นั้นเอง ตัวอย่างคำสั่งใน command-line ในการ compile
vbc /nowarn
และ
vbc /warnaserror+
หมายเหตุ - บทความนี้ตอนแรกคิดว่าไม่ยาว แต่เอาเข้าจริงกลับยาวมาก ทั้งนี้เพราะต้องมีตัวอย่างโค้ด และต้องการอธิบายพอสังเขป จึงจะเกิดประโยชน์จริง ขออภัยที่ใช้เวลาเขียนบทความนี้นาน
แหล่งข้อมูล :
Microsoft - What's New in the Visual Basic Language
Microsoft - What's New in the .NET Framework Version 2.0