วันอังคารที่ ๓๑ กรกฎาคม พ.ศ. ๒๕๕๐

Value Types (1) : Built-in Types

Value Type หรือ Primitive Types คือ ชนิดข้อมูลพื้นฐาน ที่มีการเก็บค่า (allocate) ในหน่วยความจำเป็นแบบ stack และสืบทอด (derive) มาจาก System.ValueType ซึ่งมีความเร็วในการทำงานมากกว่า แบบ Reference Type (type ชนิดนี้แหละครับ ที่เมื่อมีอยู่ในภาษา Object-Oriented ใดแล้ว ภาษานั้นจะถูกเรียกว่า Hybrid Object-Oriected เพราะไม่ถือว่าเป็น OO เต็มรูปแบบ แต่ก็มีข้อดี คือทำงานได้เร็วขึ้น ซึ่งสังเกตได้ว่า value types นี้ จะเป็น type ที่ใช้บ่อยๆ เช่น ตัวเลข เป็นต้น ส่วนถ้าเป็นภาษาที่ใช้ความสามารถ OO เต็มรูปแบบ จะเรียกว่า Pure Object-Oriented เช่น ภาษา SmallTalk, Ruby, Eiffel เป็นต้น) value types แบ่งออกเป็น 3 ประเภท คือ

1. Built-in types
2. User-defined types
3. Enumerations (Sealed Value Types)

Built-in types
มี built-in types กว่า 300 ชนิด แต่ในที่นี้ผมจะขอแนะนำเฉพาะที่น่าสนใจ เช่น

ตัวเลขจำนวนเต็ม


SByte (System.SByte/sbyte) -128 ถึง 127
Byte (System.Byte/byte) 0 ถึง 255
ขนาด 1 byte (8 bits)
Short (System.Int16/short) -32,768 ถึง 32,767
UShort (System.UInt16/ushort) 0 ถึง 65,535
ขนาด 2 byte (16 bits)
Integer (System.Int32/int) -2,147,483,648 ถึง 2,147,483,647
UInteger (System.Int32/uint) 0 ถึง 4,294,967,295
ขนาด 4 byte (32 bits)
Long (System.Int64/long) -9,223,372,036,854,775,808 ถึง 9,223,372,036,854,775,807
ULong (System.UInt64/ulong) 0 ถึง 18,446,744,073,709,551,615
ขนาด 8 byte (64 bits)


ตัวเลขทศนิยม

Single (System.Single/float)
-3.402823E38 ถึง -1.401298E-45 และ 1.401298E-45 ถึง 3.402823E38 (ความถูกต้องของทศนิยม 7 หลัก)
ขนาด 4 byte (32 bits)
Double (System.Double/double)
-1.79769313486231E308 ถึง -4.94065645841247E-324 และ 4.94065645841247E-324 ถึง 1.79769313486232E308 (ความถูกต้องของทศนิยม 15-16 หลัก)
ขนาด 8 byte (64 bits)
Decimal (System.Decimal/decimal)
กรณีจำนวนเต็ม +/- 79,228,162,514,264,337,593,543,950,335
และกรณีทศนิยม +/-7.9228162514264337593543950335 (ความถูกต้องของทศนิยม 28 หลัก)
ขนาด 16 byte (128 bits)

อื่นๆ

Char (System.Char/char)
ข้อมูลตัวอักษร 1 ตัว เป็น Unicode
ขนาด 2 bytes (16 bits)
ฺBoolean (System.Boolean/bool)
ข้อมูลทางตรรกะ(logic) มีค่าเป็น True หรือ False
ขนาด 4 bytes (32 bits)
Date (System.DateTime/date) ตั้งแต่ 1/1/0001 12:00:00 AM ถึง 12/31/9999 11:59:59 PM
ข้อมูลวันเวลา
ขนาด 8 bytes (64 bits)
System.IntPtr
ข้อมูล Pointer ที่ชี้ไปยัง address ใน memory
ขนาดขึ้นกับ platfrom ที่ framework อยู่

ทิปเทคนิค :
** เมื่อมีการใช้ชนิดข้อมูลที่เป็นจำนวนเต็ม แนะนำให้ใช้ Integer หรือ UInteger เพราะ CLR ถูกปรับมาให้ทำงานกับตัวเลขจำนวนเต็ม ขนาด 32-bits ได้มีประสิทธิภาพมากกว่าชนิดอื่น
** Value type จะมี method เช่น ToString มาให้ เพราะทุกๆ type ทั้ง value types และ reference types ก็ล้วนแล้วแต่สืบทอดมาจาก System.Object นั้นเอง

แหล่งข้อมูล :
Reference and Value Types by William Ryan
Programming in .NET: The Type System - Addison-Wesley Professional
Primitive, Reference and Value Types by Nadeem Afanah - CodeProject

วันเสาร์ที่ ๒๑ กรกฎาคม พ.ศ. ๒๕๕๐

ตัวอย่างการใช้ไอทีอย่างไม่เหมาะสม (Bad IT Solution)

ภาพบนจากหน้า 1 เดลินิวส์ ฉบับวันที่ 10 ก.ค.50 ซึ่ง นศ.คนขวามือสุดอีกคน ที่อยู่กลางภาพประคองพระบรมฉายาลักษณ์ไว้กับหน้าอก ขณะที่ภาพจากหน้า 1 ไทยรัฐ เหตุการณ์เดียวกันและมุมเดียวกัน แต่ภาพพระบรมฉายาลักษณ์หายไป

ถ้าเป็นภาพส่วนตัวคงไม่มีใครว่าอะไรหรอกนะ แต่นี้ดันเป็นหนังสือพิมพ์ระดับประเทศ ที่มีคนอ่านเยอะมาก แบบนี้รูปข่าวอื่นๆ ที่ผ่านมาหรือในอนาคต จะตกแต่งภาพมาอีกรึเปล่า เซ็งจริงๆ ประเทศไทย คิดว่าจะมีแต่ในอีเมล์ซะอีก

เข้าไว้อาลัยแด่ คนใช้ IT ที่มีจรรยาบรรณ หรือจริธรรมน้อยมาก (แล้วก็จะมีเสียงผู้ตกแต่งออกมาว่า ผมทำตามคำสั่งเจ้านายครับ... อืมม เอาหน้าไอ้เจ้านายมาให้ดูหน่อยสิ)

สุดท้ายนิทานเรื่องนี้สอนให้รู้ว่า ความเจริญของชาติอยู่ที่คน ไม่ใช่เทคโนโลยี

ปล. ไม่ต้องไปค้นในเว็บนะ เพราะรูปไม่ได้แต่ง มีแต่ในหนังสือพิมพ์ ฉบับวันที่ 10 กค. 50 เท่านั้น (พิมพ์นิยม น่าสะสม)

เข้ารหัส/ถอดรหัส ด้วย Columnar Transposition Cipher (Columnar Transposition Cipher with VB.NET)

Columnar Transposition Cipher เป็นอัลกอริทึมที่คล้ายกับ Rail Fence Cipher ซึ่งมีความแตกต่างกันที่วิธีอ่านและเขียน โดยจะเขียนตามแนวแถว และอ่านตามแนวคอลัมน์ในเมตริกซ์ รวมทั้งลำดับคอลัมน์ในการอ่าน อัลกอรึทึมนี้อาจจะต้องเพิ่มการตรวจสอบ input จาก user ในการกรอก key เพราะต้องเป็นตัวเลขที่ไม่ซ้ำ แต่ต่อเนื่องและไม่ต้องเรียงลำดับ ซึ่งในที่นี้จะให้เริ่มที่ 1 ถึง 9
จากรูปซ้าย เมื่อเข้ารหัสแล้วจะได้ผลลัพธ์ ดังนี้ EVLNE ACDTK ESEAQ ROFOJ DEECU WIREE กรณีเมตริกซ์ไม่เต็ม แบบรูปขวา ให้อ่านข้ามช่องว่าง (ในโค้ดจะใส่ค่า Nothing ลงไป) ไปได้เลย ผลลัพธ์คือ EVLNA CDTES EAROF ODEEC WIREE

ตัวอย่างโค้ดการเข้ารหัส(Encrypt) แบบ Columnar Transposition Cipher

Function Encrypt(ByVal PlainText As String, ByVal Key As String) As String
'หาจำนวนคอลัมน์
Dim ColumnNum As Byte = Key.Length

'หาจำนวนแถว
Dim RowNum As Byte = PlainText.Length \ Key.Length
If (PlainText.Length Mod Key.Length) > 0 Then RowNum += 1

Dim CharMatrix(RowNum - 1, ColumnNum - 1) As Char
Dim CharArray(CharMatrix.Length - 1) As Char

'นำตัวอักษรใน PlainText มาเรียงในเมตริกซ์ (Array 2 มิติ)
'เรียงจากซ้ายไปขวาทีละแถว
Dim Count As Byte = 0
For CountRow As Byte = 0 To RowNum - 1
For CountCol As Byte = 0 To ColumnNum - 1
If Count <= PlainText.Length - 1 Then
CharMatrix(CountRow, CountCol) = PlainText(Count)
Count += 1
Else
CharMatrix(CountRow, CountCol) = Nothing
End If
Next CountCol
Next CountRow

'อ่านตัวอักษรในเมตริกซ์ จากบนลงล่าง ทีละคอลัมน์
'มาเรียงเป็นข้อความแถวเดียว
Count = 0
For CountCol As Byte = 1 To Key.Length
'หา column index ตามลำดับก่อนหลัง เก็บไว้ที่ตัวแปร ColumnOrder
Dim ColumnOrder As Byte
For ColumnOrder = 0 To Key.Length - 1
Dim Num As Byte = CByte(Key(ColumnOrder).ToString)
If CountCol = Num Then Exit For
Next ColumnOrder

For CountRow As Byte = 0 To RowNum - 1
If Not CharMatrix(CountRow, ColumnOrder) = Nothing Then
CharArray(Count) = CharMatrix(CountRow, ColumnOrder)
Count += 1
End If
Next CountRow
Next CountCol

'ส่งค่าตัวอักษรที่เป็น array กลับเป็น string
Return CharArray
End Function

ตัวอย่างโค้ดการถอดรหัส(Decrypt) แบบ Columnar Transposition Cipher

Function Decrypt(ByVal CipherText As String, ByVal Key As String) As String
'หาจำนวนคอลัมน์
Dim ColumnNum As Byte = Key.Length

'หาจำนวน cell ว่าง
Dim EmptyNum As Byte
Dim CharTotal As Byte = CipherText.Length
Dim Fraction As Byte = CharTotal Mod ColumnNum
EmptyNum = IIf(Fraction = 0, 0, ColumnNum - Fraction)

'หาจำนวนแถว
Dim RowNum As Byte = CipherText.Length \ Key.Length
If (CipherText.Length Mod Key.Length) > 0 Then RowNum += 1

Dim CharMatrix(RowNum - 1, ColumnNum - 1) As Char
Dim CharArray(CharMatrix.Length - 1) As Char

'นำตัวอักษรใน CipherText มาเรียงในเมตริกซ์ (Array 2 มิติ)
'เรียงจากบนลงล่าง ทีละคอลัมน
Dim Count As Byte = 0
For CountCol As Byte = 1 To Key.Length
'หา column index ตามลำดับก่อนหลัง เก็บไว้ที่ตัวแปร ColumnOrder
Dim ColumnOrder As Byte
For ColumnOrder = 0 To Key.Length - 1
Dim Num As Byte = CByte(Key(ColumnOrder).ToString)
If CountCol = Num Then Exit For
Next ColumnOrder

'คอมลัมน์ที่ไม่มีช่องว่าง
If ColumnOrder <= (Key.Length - 1 - EmptyNum) Then
For CountRow As Byte = 0 To RowNum - 1
CharMatrix(CountRow, ColumnOrder) = CipherText(Count)
Count += 1
Next CountRow
Else 'คอมลัมน์ที่มีช่องว่าง (Nothing)
For CountRow As Byte = 0 To RowNum - 2
CharMatrix(CountRow, ColumnOrder) = CipherText(Count)
Count += 1
Next CountRow
End If
Next CountCol

'อ่านตัวอักษรในเมตริกซ์ จากซ้ายไปขวา ทีละแถว
'มาเรียงเป็นข้อความแถวเดียว
Count = 0
For CountRow As Byte = 0 To RowNum - 1
For CountCol As Byte = 0 To ColumnNum - 1
If Count <= CipherText.Length - 1 Then
CharArray(Count) = CharMatrix(CountRow, CountCol)
Count += 1
End If
Next CountCol
Next CountRow

'ส่งค่าตัวอักษรที่เป็น array กลับเป็น string
Return CharArray
End Function

แหล่งข้อมูล :
Transposition cipher - wikipedia
Cryptography/Transposition ciphers - wikibooks
Transposition ciphers - Torbjörn Andersson
Columnar Transposition Ciphers - The Contest Center
Braingle - มีโปรแกรมให้เล่น

วันพุธที่ ๔ กรกฎาคม พ.ศ. ๒๕๕๐

ศิลปะการใช้ If (Art of If Statement)

บางคนอาจจะถามว่า จะเขียนทำไม ไอ้เรื่องกล้วยๆ ขนาดนี้ ซึ่งผมก็ไม่เถียงครับ เพราะมันเป็นพื้นฐานของตรรกะการเขียนโปรแกรมอยู่แล้ว แต่สิ่งที่ผมจะเอามาบอกไม่ใช่มาอธิบาย เรื่อง If ใช้งั้นยังครับ แต่เป็นรูปแบบ If ที่สามารถเขียนได้หลายรูปแบบ บางรูปแบบหลายๆ คนอาจจะยังไม่เคยเห็นเลยนะ้ครับ... น่าสนใจแล้วใช่ไหมครับ งั้นเราลองมาดูกันว่ามีอะไรบ้าง เริ่มจากที่เห็นบ่อยๆ ไปจนถึงที่ไม่ค่อยเห็นครับ

1. แบบมี End If (หรือแบบหลายบรรทัด)
1.1) If ... End If
รูปแบบนี้ เราจะตรวจสอบและเขียนคำสั่ง กรณีผลลัพธ์ของเงื่อนไขเป็น True เท่านั้น เช่น

'กรณีผลลัพธ์ของเงื่อนไขเป็น False คำสั่งถัดไปจะเป็น End If ทันที
If ValueA > 2 Then
ValueA -= 1
ValueB = 3
End If


1.2) If ... Else ... End If
รูปแบบนี้ เราจะตรวจสอบและเขียนคำสั่ง ที่ผลลัพธ์ของเงื่อนไขเป็นทั้ง True และ False เช่น

If ValueA <> 3 Then
ValueB += 1
Else
ValueB -= 1
End If


1.3) If ... ElseIf ... Else ... End If
รูปแบบนี้จะให้เราใส่เงื่อนไขเข้าไปหลายๆ ตัวได้ คล้ายๆ Select Case ส่วน Else จะใสหรือไม่ก็ได้ แต่ถ้าไม่ใส่จะเป็นการเขียนโปรแกรมที่ไม่ดี เพราะกรณีเงื่อนไขใดๆ ไม่มีผลลัพธ์เป็น True เลย ก็อาจจะเกิดปัญหา logic error หรือ flow ไม่เป็นไปตามต้องการก็ได้ จึงควรเขียนดักไว้ก่อน เพื่อให้ถูกหลักการเขียนโปรแกรมที่ดี (อาจมีเหตุการณ์แปลกๆ ที่ทำให้มี input data แปลกๆ เข้ามาในโปรแกรมเรา กันไว้ดีกว่าแก้ครับ) ตัวอย่างการใช้

If MyCountry = "Thailand" Then
MyCountry = "ประเทศไทย"
ElseIf MyName = "Japan" Then
MyCountry = "ประเทศญี่ปุ่น"
ElseIf MyName = "China" Then
MyCountry = "ประเทศจีน"
Else
MyCountry = "บุคคลไร้สัญชาติ"
End If


2. แบบไม่มี End If (หรือแบบบรรทัดเดียว)
2.1) If ... Then ...
เป็นรูปแบบที่สั้นที่สุด และหวังผลให้ทำงานเฉพาะผลลัพธ์ของเงื่อนไขที่เป็น True เท่านั้น แต่คำสั่งหลัง Then มีได้แค่ 1 statement เท่านั้น ตัวอย่างเช่น

If Number = 10 Then MsgBox("Value is " & Number)

2.2) If ... Then ... Else ...
รูปแบบ If บรรทัดเดียว ที่ทำงานกับผลลัพธ์ชองเงื่อนไข ทั้ง True และ False แต่คำสั่งหลัง Then และ Else ก็ยังต้องมีเพียง 1 statement เท่านั้น เช่น

If Score <= 49 Then Grade = "S" Else Grade = "P"


2.3) If ... Then ... : ... : ...
รูปแบบ If บรรทัดเดียว ที่ทำงานกับผลลัพธ์ชองเงื่อนไขที่เป็น True แต่สามารถเขียนหลายๆ statement หลัง Then ได้ โดยมีเครื่องหมานโคล่อน (:) ระหว่าง statement

If Sex = True Then SexString = "Man" : MsgBox("Sex is " & SexString)

2.4) If ... Then ... : ... : ... Else ... : ... : ...
รูปแบบที่เหมือนข้อ 2.3 แต่ทำงานกับผลลัพธ์ชองเงื่อนไข ทั้ง True และ False และเขียนหลายๆ statement หลังตรวจสอบการเงื่อนไข ได้เหมือนกัน

If Value > 3 Then X *= 2 : Y *= 3 Else X *= 3 : Y *=2 : Z *= 2

3. แบบ IIf (อ่านว่า If and only If)
รูปแบบนี้จะมีการ return ค่าหลังจากตรวจสอบเงื่อนไข ซึ่งเขียนได้ในบรรทัดเดียวด้วย รูปแบบเป็นดังนี้ IIF(เงื่อนไข, ค่าเมื่อเงื่อนไขเป็นจริง, ค่าเมื่อเงื่อนไขเป็นเท็จ) ตัวอย่างเช่น

'คำสั่ง IIf จะทำงานเหมือน call function
Price = IIf(IsMember, Price - (Price * 0.1), Price - (Price * 0.05))

เทคนิคเพิ่มเติม
เพื่อให้การเขียนแต่ละบรรทัดไม่ยาวเกินไป เราอาจจะใช้เครื่องหมาย underscore (_) เพื่อขึ้นบรรทัดใหม่ แต่ compiler จะตีความเป็นเหมือนบรรทัดเดียว ทำให้โค้ดมีระเบียบและมีประสิทธิภาพดี เช่น

'โค้ดข้างล่างนี้ มีรูปแบบเหมือนข้อ 2.1
If
(CustomerItem => 3) Or (CustomerTotal > 2000) _
Or (CustomerBirthday = Now) Or (IsMember) Then _
Price -= Price * 0.1

หมายเหตุ
ถ้าใช้เหตุผลทาง Software Engineering แล้ว รูปแบบที่ 2.3 และ 2.4 ไม่ควรนำมาใช้เป็น Coding Standard สำหรับการผลิตซอฟต์แวร์ขนาดใหญ่ บางที่อาจเข้มงวดมาก โดยให้ใช้เพียงแค่รูปแบบที่ 1 ยังไงก็ใหเรียนรู้ไว้บ้างก็ดี เพราะซอฟต์แวร์บางตัวก็อาจจะเน้น performance มากๆ หรือเป็นโปรแกรมไม่ใหญ่ จะได้มีลกูเล่นไว้สร้างสีสันบ้าง ยิ่งเป็น junior ยิ่งควรต้องศึกษา เผื่อต้องทำงานร่วมกับ senior ที่มีนิสัยชอบ advance coding (คำเตือน - ไม่ควรเขียนโปรแกรมแกล้งรุ่นน้อง เพราะอาจได้รับการกราบไหว้ แต่ไม่มีใครอยากทำงานด้วย 555...)

VB.NET VS. C#

ถ้าจะถามผมว่า ผมชอบภาษาอะไรมากที่สุด ผมก็คงจะตอบว่า Python ครับ เพราะผมเป็นพวกชอบความสะอาด มีระเบียบ(แต่ไม่ชอบมีวินัยนะครับ) และชอบศาสตร์ทางด้าน Software Engineering ซึ่งภาษา Python ก็สนับสนุนคุณสมบัติอย่างที่ผมว่ามา และยังมีคุณสมบัติอื่นๆ อีกมากมายที่น่าสนใจ แต่ผมคงพูดถึงภาษานี้โดยละเอียดอีกทีในเรื่องที่เกี่ยวกับ IronPython

แต่ถ้าจะถามใหม่ว่า ภาษาบน .NET Framework ที่ผมชอบมากที่สุด คือ ภาษาอะไร คำตอบที่แน่นอนอยู่แล้ว ก็คือ VB.NET แต่ผู้อ่านหลายท่านก็เลือก C# เป็นคำตอบ เอาเป็นว่าเรื่องที่ว่า VB.NET กับ C# ภาษาไหนดีกว่ากันนั้น ตอบยากครับ เพราะมันมีหลายปัจจัยให้พิจารณา เช่น พื้นฐานภาษาของผู้พัฒนา, ประเภทของซอฟต์แวร์ที่จะพัฒนา, ข้อจำกัดเวลาในการพัฒนา เป็นต้น ซึ่งเรื่องนี้ผมจะพยายามนำมาเสนอบ่อยๆ ตามแต่จะมีโอกาสครับ

สำหรับวันนี้ผมขอนำเสนอข้อมูล ของอาจารย์สุเทพ ที่เขียนตอบเรื่อง เปรียบเทียบ C#.net กับ vb.net ไว้ใน Software Development Discussion Board อย่างน่าสนใจ จึงขอนำข้อมูลนั้นมาเสนอไว้ให้อ่านกัน และผมจะเสริมข้อมูลเพิ่มในภายหลัง

"... เปรียบเทียบ C#.net กับ vb.net
การเลือกระหว่างภาษา C#.Net และ VB.Net มักเป็นข้อที่หลายคนคิดในช่วงวางแผนก่อนที่จะเริ่ม ลงทุนลงแรงเพื่อศึกษาและนำมาใช้ในการพัฒนาระบบขึ้นมา


ข้อเสนอแนะอย่างง่ายที่สุดของไมโครซอฟต์ ก็คือว่าเรามีความชำนาญ มีความคุ้นเคย ชอบพอกับภาษาใดมาก่อน ก็ให้เลือกภาษาที่เป็นแนวเดียวกันนั้น เนื่องจากทุกภาษาใน .Net จะถูกแปลเป็นภาษา Microsoft Intermediate Language (MSIL) โดยเฉพาะสองภาษา ที่จะเปรียบเทียบกันนี้ ถ้าเขียนโค้ด VB.Net อย่างถูกต้องดี รหัส MSIL ที่ได้ ก็แทบจะเหมือนกันเลย ดังนั้น performance ของงานที่ได้ ก็จะไม่แตกต่างกัน นี่เป็นการยกระดับงาน Visual Basic เป็นอย่างมาก แล้วการที่ VB.Net ใช้
Base Class Library ของ .Net framework ร่วมกันกับ C# ก็ทำให้ VB.Net programmer ถือเป็น first-class citizen ไปแล้ว


การเขียนโค้ด VB.Net อย่างถูกต้องดี เช่นมีการใช้ Option Strict On
หรือมีการใช้ DirectCast แทนที่จะใช้ CType เป็นต้น.


รายละเอียดการเปรียบเทียบสองภาษา ในข้อความนี้ รวบรวมประมวลมาจากแหล่งข้อมูลต่างๆ หลายแห่ง
ซึ่งอาจจะต้องมีการพูดถึงศัพท์หรือเทคนิคลึกๆ บ้างเพื่อให้ได้ความสมบูรณ์นะครับ


ดูข้อดีของ Visual Basic .Net
- รองรับ Optional argument ซึ่งสำคัญมากที่คุณต้องการใช้งานร่วมกับ ActiveX component หรือการเขียนโค้ดชนกับพวก Office
- ทำตัวไม่ซีเรียสได้ คือยอมรับการทำ late-binding ได้ ถ้าไม่กำหนด Option Strict On การเขียนโค้ดพวกนี้ใช้กับพวก ActiveX อีกนั่นเอง (ผมแนะนำให้หลีกเลี่ยงการเขียนโค้ดแบบ late-binding ใน .Net)
- รองรับการทำ named indexer (การสร้าง property ที่มี argument)
- มีคำสั่ง VB แบบเดิมๆ เช่น Left, Mid, UCase, ... ให้ใช้ง่ายๆ สำหรับผู้ใช้ VB6 มาก่อน (การเรียกใช้ฟังก์ชันแบบเดิมๆ นี้จะมีผลต่อประสิทธิภาพของโปรแกรม)
- มีประโยค With..End With ให้ใช้
- ความเรียบง่าย เช่นการสร้างประโยค Event
- สามารถกำหนดชื่อเมธอดของการ implements interface ที่ต่างจากที่กำหนดไว้ใน interface ได้ (ผมว่าไม่ค่อยได้ประโยชน์เลย ทำให้ยุ่งยากในการค้นหาเสียมากกว่า)
- มีประโยค Catch...When... ทำให้สามารถทำการ filter exception ด้วยเงื่อนไขได้ นอกเหนือจากการ filter ด้วยชนิดของ exception เท่านั้น
- Visual Studio .Net จะทำการ compile โค้ดในลักษณะ background ซึ่งช่วยเป็นข้อดีในโปรเจ็กต์ขนาดเล็ก แต่ถ้าโปรเจ็กต์ขนาดใหญ่มหึมา จะกลับเป็นข้อเสียอย่างมาก (มีฝรั่งหลายคนบ่นว่าต้องถึงกับต้องยอมเปลี่ยนจาก VB.Net มาเป็น C# เลย ในโปรเจ็กต์ที่มีไฟล์มีคลาสเป็นพันๆ)


ข้อดีของ C# .Net
- รองรับ XML documentation คล้ายๆ javadoc คือเอาคอมเม้นต์ในโค้ดมาแปลงเป็นเอกสาร technical manual ได้เลย แต่ใน VB.Net เวอร์ชั่น 2005 (Whidbey) ก็จะรองรับในคุณสมบัตินี้ด้วย
- สามารถทำ operator overloading ได้ (VB.Net 2005 ก็จะทำได้เช่นกัน)
- รองรับ unsigned datatype (VB.Net 2005 ก็จะทำได้เช่นกัน)
- มีประโยค using เพื่อใช้จัดการกับ resource ที่เป็นแบบ unmanaged
- รองรับ unsafe code


สังเกตได้ว่า อะไรที่ใน C# มี ซึ่งเป็นสิ่งที่ซับซ้อน ใน VB.Net เวอร์ชันถัดไป ก็จะมีด้วย แต่มักจะถูกนำมาแสดงในรูปแบบที่ง่ายต่อความเข้าใจ แต่อะไรที่ VB.Net มี มักจะไม่ถูกนำไปเพิ่มให้กับ C# เช่นรูปแบบการสร้าง event ที่เรียบง่าย อย่างประโยค Handles หรือคีย์เวิร์ด My ที่จะมีใน VB.Net Whidbey (คิดว่าใน C# อาจจะไม่มี) หรือ Optional argument (ใน C# แก้ปัญหานี้ด้วยการทำ overloading แต่ก็จะไม่สามารถใช้งานร่วมกับ ActiveX component แบบเดิมได้อยู่ดี)


ถ้าขนาดของโปรเจ็กต์ที่คุณคิดว่าจะต้องทำในอนาคตใหญ่มากๆ ก็ควรจะเลือก C# ไปเสียแต่แรกเลย เว้นแต่จะมีวิธีแก้ปัญหา IDE ที่ช้ามากๆ เมื่อมีไฟล์จำนวนมากของ VB.Net ได้


เขาว่าภาษา VB.Net เป็น 4GL (ภาษา Generation ที่สี่) แต่ภาษา C# ถูกวางเป็น 3GL กว่าๆ คือสูงกว่า 3GL เช่น C++ แต่ไม่ถึง 4GL


ถ้าเอาความอย่างที่ Microsoft วาง position ไว้
ภาษา VB .Net เป็น task-oriented
ภาษา C# .Net เป็น code-focused


ถ้าเอามาสร้าง application ทางธุรกิจ ภาษา VB.Net จะเป็นตัวเลือกที่ยอดเยี่ยมอย่างปฏิเสธไม่ได้ เนื่องจากแทนที่โปรแกรมเมอร์จะไม่ต้องคำนึงถึงเรื่องลึกๆ ที่เรียนกันในวิชาของพวก computer science กันบ่อยๆจึงเรียกว่ามี productivity ดี เพราะเอาเวลามาสร้างงานเลย


แต่นั่นก็เป็นอีกเหตุผลหนึ่งว่า ถ้าใช้ C# ศัพท์แสงในเนื้อภาษาจะเป็นศัพท์แบบที่ใช้ในวงการ computer science เช่น abstract, static เป็นต้น ซึ่งจะจำเป็นถ้าต้องมีการใช้เครื่องมืออย่างพวก Rational Rose หรือ Modeling tools อื่นๆ


สิ่งที่รวบรวมมารวมกับความคิดเห็นเพิ่มเติมบางอย่างนี้เข้าไปมีทั้งด้าน รูปแบบภาษา การใช้งานจริง และแฟกเตอร์อื่นๆ อาจจะมีข้อผิดพลาดบ้าง ถ้ามีก็ช่วยบอกเพื่อปรับปรุงเพิ่มเติมต่อไปนะครับ..."


และมีข้อมูลอย่างหนึ่งที่น่าสนใจ คือ ถ้านำนักพัฒนาที่ถนัดภาษา VB.NET มาจับเขียนภาษา C# (แบบไม่ให้เตรียมตัวนะครับ) จะพบว่าสามารถเขียนได้จำนวนมาก แต่ถ้านำนักพัฒนาที่ถนัดภาษา C# มาจับเขียนภาษา VB.NET กลับพบว่ามีจำนวนน้อยที่เขียนได้ ผมสันนิษฐานว่า ไม่ใช่เพราะกลุ่ใไหนฉลาดกว่ากัน แต่เป็นเพราะความสนใจมากกว่า ผมว่านักพัฒนาที่ถนัด C# จะไม่เปิดใจรับภาษา VB.NET ว่าเป็นพี่น้องกันใน .NET Framework เลย


แหล่งข้อมูล :
เปรียบเทียบ C#.net กับ vb.net
Why C# Is Not a "Better" Language Than VB.NET
Top 10 reasons VB.NET is better than C#
Top 10 reasons C# is better than VB.NET
Complete Comparison for VB.NET and C#

VB.NET 2005 มีอะไรใหม่ (What's new in VB.NET 2005)

มีหลายคนสงสัยว่า 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