ข้อดีของ ภาษา C# เมื่อเทียบกับภาษาอื่น ๆ ตอนที่ 2

ลาก่อนเฮดเดอร์ไฟล์
ข้อดีอีกอย่างหนึ่งของภาษาซีชาร์พเมื่อเทียบกับภาษาซี คือเราสามารถอ้างถึงตัวแปรหรือเมธอดที่อยู่ในไฟล์อื่นได้โดยไม่ต้องสร้าง “เฮดเดอร์ไฟล์” (ซอร์สไฟล์ที่มีนามสกุล .h)
แล้วจึงใช้คำสั่ง #include เพื่อบอกให้คอมไพเลอร์รู้ว่าสิ่งที่อ้างถึงนั้นอยู่ในไฟล์ไหน
ที่เป็นอย่างนั้นเพราะคอมไพเลอร์ภาษาซีชาร์พจะตรวจสอบซอร์สไฟล์ทั้งหมดภายในโปรเจ็กต์ให้โดยอัตโนมัติ

คำอธิบายภาพ: นี่คือตัวอย่างโค้ดเป็นซอร์สไฟล์ชื่อ main.c
มีคำสั่งเรียกฟังก์ชันที่อยู่ในเฮดเดอร์ไฟล์ตรงบรรทัดที่ 7
ในภาษาซี หากเราต้องการนำฟังก์ชันไปไว้ในซอร์สไฟล์อีกไฟล์หนึ่งโดยเฉพาะ
เพื่อให้เรียกใช้งานจากหลาย ๆ แห่งได้ง่ายเราจะสร้างเฮดเดอร์ไฟล์
จากนั้นเมื่อโค้ดในซอร์สไฟล์ใดต้องการอ้างถึงตัวแปรหรือฟังก์ชันที่อยู่ในเฮดเดอร์
จะต้องใส่คำสั่ง #include ซึ่งไม่ใช่คำสั่งในภาษาซี
แต่เป็นคำสั่งประเภทคอมไพเลอร์ไดเรกตีฟ (Compiler directive) ทำหน้าที่บอกให้คอมไพเลอร์รู้ว่าให้ไปตรวจหาฟังก์ชันนั้นจากเฮดเดอร์ไฟล์ชื่ออะไร
ตัวอย่างโค้ดในภาพนี้ คือ ซอร์สไฟล์ชื่อ main.c ที่ต้องการเรียกใช้งานฟังก์ชัน add
แต่เรานิยามฟังก์ชัน add() ไว้ในเฮดเดอร์ไฟล์ชื่อ Header1.h
ดังนั้นจึงต้องใส่คำสั่ง #include “Header1.h” ไว้ในบรรทัดที่ 2
จากนั้นเราจึงเรียกใช้ฟังก์ชัน add() ในบรรทัดที่ 7
การทำเช่นนี้ไม่ค่อยสะดวกนัก เพราะหากอ้างถึงฟังก์ชันจากหลายเฮดเดอร์ จะเกิดมีรายการ #include อย่างยืดยาว
และถ้ามีการแบ่งซอร์สไฟล์ไปอีกหลาย ๆ เฮดเดอร์ไฟล์ และในแต่ละเฮดเดอร์ไฟล์เองก็อ้างถึงฟังก์ชันในเฮดเดอร์ไฟล์อื่นอีกเป็นทอด ๆ
หากไม่ระมัดระวังก็จะมีโอกาสเกิดการอ้างถึงพัวพันเป็นวงรอบแบบงูกินหางได้ง่าย
มีคำสั่งเรียกฟังก์ชันที่อยู่ในเฮดเดอร์ไฟล์ตรงบรรทัดที่ 7
ในภาษาซี หากเราต้องการนำฟังก์ชันไปไว้ในซอร์สไฟล์อีกไฟล์หนึ่งโดยเฉพาะ
เพื่อให้เรียกใช้งานจากหลาย ๆ แห่งได้ง่ายเราจะสร้างเฮดเดอร์ไฟล์
จากนั้นเมื่อโค้ดในซอร์สไฟล์ใดต้องการอ้างถึงตัวแปรหรือฟังก์ชันที่อยู่ในเฮดเดอร์
จะต้องใส่คำสั่ง #include ซึ่งไม่ใช่คำสั่งในภาษาซี
แต่เป็นคำสั่งประเภทคอมไพเลอร์ไดเรกตีฟ (Compiler directive) ทำหน้าที่บอกให้คอมไพเลอร์รู้ว่าให้ไปตรวจหาฟังก์ชันนั้นจากเฮดเดอร์ไฟล์ชื่ออะไร
ตัวอย่างโค้ดในภาพนี้ คือ ซอร์สไฟล์ชื่อ main.c ที่ต้องการเรียกใช้งานฟังก์ชัน add
แต่เรานิยามฟังก์ชัน add() ไว้ในเฮดเดอร์ไฟล์ชื่อ Header1.h
ดังนั้นจึงต้องใส่คำสั่ง #include “Header1.h” ไว้ในบรรทัดที่ 2
จากนั้นเราจึงเรียกใช้ฟังก์ชัน add() ในบรรทัดที่ 7
การทำเช่นนี้ไม่ค่อยสะดวกนัก เพราะหากอ้างถึงฟังก์ชันจากหลายเฮดเดอร์ จะเกิดมีรายการ #include อย่างยืดยาว
และถ้ามีการแบ่งซอร์สไฟล์ไปอีกหลาย ๆ เฮดเดอร์ไฟล์ และในแต่ละเฮดเดอร์ไฟล์เองก็อ้างถึงฟังก์ชันในเฮดเดอร์ไฟล์อื่นอีกเป็นทอด ๆ
หากไม่ระมัดระวังก็จะมีโอกาสเกิดการอ้างถึงพัวพันเป็นวงรอบแบบงูกินหางได้ง่าย

คำอธิบายภาพ: นี่คือไฟล์ Header1.h ซึ่งมีนิยามฟังก์ชัน add()
โดยฟังก์ชันนี้รับพารามิเตอร์สองตัวคือ a และ b
การทำงานเพียงแค่นำค่าที่ได้รับจากพารามิเตอร์มาบวกกันแล้วส่งผลลัพธ์กลับให้ผู้เรียก
โดยฟังก์ชันนี้รับพารามิเตอร์สองตัวคือ a และ b
การทำงานเพียงแค่นำค่าที่ได้รับจากพารามิเตอร์มาบวกกันแล้วส่งผลลัพธ์กลับให้ผู้เรียก

คำอธิบายภาพ: ผลลัพธ์การทำงานของโปรแกรม บรรทัดที่เห็นเป็นเลข 3
คือผลจากการทำงานของโค้ดบรรทัดที่ 7
และบรรทัดที่เห็นเป็นคำว่า End.
คือผลจากการทำงานของโค้ดบรรทัดที่ 8
ภาษาซีชาร์ฟได้แก้ปัญหาหรือความไม่สะดวกของการใช้เฮดเดอร์ไฟล์ในภาษาซี
โดยการใช้เนมสเปส (Name Space) เหมือนภาษาซีพลัสพลัสและจาวา
หากสิ่งที่ต้องการอ้างถึงอยู่ภายในเนมสเปสเดียวกันก็จะสามารถอ้างถึงได้ทันที
โดยไม่ต้องระบุชื่อซอร์สไฟล์
เพราะคอมไพล์เลอร์สามารถค้นหาชื่อที่อ้างถึงได้แม้จะอยู่คนละซอร์สไฟล์กันได้โดยตรง
คือผลจากการทำงานของโค้ดบรรทัดที่ 7
และบรรทัดที่เห็นเป็นคำว่า End.
คือผลจากการทำงานของโค้ดบรรทัดที่ 8
ภาษาซีชาร์ฟได้แก้ปัญหาหรือความไม่สะดวกของการใช้เฮดเดอร์ไฟล์ในภาษาซี
โดยการใช้เนมสเปส (Name Space) เหมือนภาษาซีพลัสพลัสและจาวา
หากสิ่งที่ต้องการอ้างถึงอยู่ภายในเนมสเปสเดียวกันก็จะสามารถอ้างถึงได้ทันที
โดยไม่ต้องระบุชื่อซอร์สไฟล์
เพราะคอมไพล์เลอร์สามารถค้นหาชื่อที่อ้างถึงได้แม้จะอยู่คนละซอร์สไฟล์กันได้โดยตรง

คำอธิบายภาพ : โค้ดภาษาซีชาร์พ เมธอด Main() ที่เรียกใช้ฟังก์ชัน Add
ต่อไปมาดูตัวอย่างซอร์สโค้ดภาษาซีชาร์พ เมธอด Main()
คำสั่งบรรทัด 1 ทำหน้าที่บอกให้คอมไพเลอร์รู้ว่าถ้าหาอะไรไม่เจอ (เช่นเมธอด) ให้ไปดูในแอสเซมบลี้ชื่อ System ที่เป็นแหล่งรวมเบสคลาสไลบรารีของดอตเน็ตเฟรมเวิร์ค
เพราะในโปรแกรมนี้เราจะใช้เมธอดชื่อ WriteLine() เพื่อทำหน้าที่แสดงผลลัพธ์ที่คอนโซล และเมธอดนี้อยู่ภายใน System
บรรทัดที่ 3 ทำหน้าที่ประกาศเนมสเปส (name space) ซึ่งเป็นแนวคิดของการจัดกลุ่มสิ่งต่าง ๆ
เช่น คลาส อินเตอร์เฟส อีนัม สตรัค ฯลฯ ไว้เป็นหมวดหมู่ เพื่อป้องกันการใช้ชื่อซ้ำกัน
ใช้จะแก้ปัญหาในกรณีที่มีผู้เขียนโค้ดหลายคนหรือโค้ดมาจากหลายแหล่ง และอาจมีการตั้งชื่อสิ่งต่าง ๆ ซ้ำ
หากอยู่คนละเนมสเปสกันคอมไพเลอร์จะถือว่าเป็นคนละคนละตัวกัน และเราสามารถอ้างถึงสิ่งนั้น ๆ ได้ โดยใส่ชื่อเนมสเปสนำหน้า
ยกตัวอย่างเช่นในเนมสเปส a มีเมธอดชื่อ Hello() และในเนมสเปส b ก็มีเมธอดชื่อ Hello() ซ้ำกัน
แต่คอมไพเลอร์จะถือว่าเป็นคนละเมธอดกัน และเราสามารถอ้างถึงเมธอด Hello() ของ a ได้
โดยเขียนว่า a.Hello() และอ้างถึงเมธอด Hello() ของ b ได้โดยเขียนว่า b.Hello()
บรรทัดที่ 7 ถึง 11 คือเมธอด Main() ซึ่งเป็นเมธอดที่จะเริ่มทำงานก่อนโดยอัตโนมัติเมื่อรันโปรแกรม
โค้ดบรรทัดที่ 9 และ 10 คือโค้ดหัวใจที่ใช้สาทิตหลักการในหัวข้อนี้
โดยบรรทัดที่ 9 เรียกใช้ฟังก์ชัน Add() ที่ไม่ได้ถูกนิยามไว้ในไฟล์นี้ แต่มีนิยามอยู่ในอีกซอร์สไฟล์หนึ่งแยกออกไป
จะเห็นว่าเราสามารถอ้างถึงฟังก์ชัน Add() ได้เลยโดยไม่ต้องบอกคอมไพเลอร์ว่าเรานิยามฟังก์ชันนี้ไว้ที่ไฟล์ชื่ออะไร
และเราสามารถที่จะคอมไพล์โปรแกรมนี้และรันได้โดยปราศจากความผิดพลาด
ต่อไปมาดูตัวอย่างซอร์สโค้ดภาษาซีชาร์พ เมธอด Main()
คำสั่งบรรทัด 1 ทำหน้าที่บอกให้คอมไพเลอร์รู้ว่าถ้าหาอะไรไม่เจอ (เช่นเมธอด) ให้ไปดูในแอสเซมบลี้ชื่อ System ที่เป็นแหล่งรวมเบสคลาสไลบรารีของดอตเน็ตเฟรมเวิร์ค
เพราะในโปรแกรมนี้เราจะใช้เมธอดชื่อ WriteLine() เพื่อทำหน้าที่แสดงผลลัพธ์ที่คอนโซล และเมธอดนี้อยู่ภายใน System
บรรทัดที่ 3 ทำหน้าที่ประกาศเนมสเปส (name space) ซึ่งเป็นแนวคิดของการจัดกลุ่มสิ่งต่าง ๆ
เช่น คลาส อินเตอร์เฟส อีนัม สตรัค ฯลฯ ไว้เป็นหมวดหมู่ เพื่อป้องกันการใช้ชื่อซ้ำกัน
ใช้จะแก้ปัญหาในกรณีที่มีผู้เขียนโค้ดหลายคนหรือโค้ดมาจากหลายแหล่ง และอาจมีการตั้งชื่อสิ่งต่าง ๆ ซ้ำ
หากอยู่คนละเนมสเปสกันคอมไพเลอร์จะถือว่าเป็นคนละคนละตัวกัน และเราสามารถอ้างถึงสิ่งนั้น ๆ ได้ โดยใส่ชื่อเนมสเปสนำหน้า
ยกตัวอย่างเช่นในเนมสเปส a มีเมธอดชื่อ Hello() และในเนมสเปส b ก็มีเมธอดชื่อ Hello() ซ้ำกัน
แต่คอมไพเลอร์จะถือว่าเป็นคนละเมธอดกัน และเราสามารถอ้างถึงเมธอด Hello() ของ a ได้
โดยเขียนว่า a.Hello() และอ้างถึงเมธอด Hello() ของ b ได้โดยเขียนว่า b.Hello()
บรรทัดที่ 7 ถึง 11 คือเมธอด Main() ซึ่งเป็นเมธอดที่จะเริ่มทำงานก่อนโดยอัตโนมัติเมื่อรันโปรแกรม
โค้ดบรรทัดที่ 9 และ 10 คือโค้ดหัวใจที่ใช้สาทิตหลักการในหัวข้อนี้
โดยบรรทัดที่ 9 เรียกใช้ฟังก์ชัน Add() ที่ไม่ได้ถูกนิยามไว้ในไฟล์นี้ แต่มีนิยามอยู่ในอีกซอร์สไฟล์หนึ่งแยกออกไป
จะเห็นว่าเราสามารถอ้างถึงฟังก์ชัน Add() ได้เลยโดยไม่ต้องบอกคอมไพเลอร์ว่าเรานิยามฟังก์ชันนี้ไว้ที่ไฟล์ชื่ออะไร
และเราสามารถที่จะคอมไพล์โปรแกรมนี้และรันได้โดยปราศจากความผิดพลาด

คำอธิบายภาพ: โค้ดภาษาซีชาร์พส่วนนิยามฟังก์ชัน Add()
ต่อไปมาดูตัวอย่างซอร์สโค้ดภาษาซีชาร์พส่วนนิยามฟังก์ชัน Add()
คำสั่งบรรทัด 1 ทำหน้าที่ระบุเนมสเปส
โปรดสังเกตว่าชื่อของเนมสเปสจะต้องตรงกันกับเนมสเปสของซอร์สโค้ดที่เรียกใช้ฟังก์ชัน Add()
ซึ่งในตัวอย่างนี้คือ Main() ที่มีเนมสเปสชื่อ csharp1
บรรทัดที่ 3 คือประกาศนิยามคลาส test1
สาเหตุที่ต้องประกาศนิยามคลาสเนื่องจากในภาษาซีชาร์พเราไม่สามารถเขียนฟังก์ชันหรือเมธอดไว้ลอย ๆ ได้
ฟังก์ชันหรือเมธอดใด ๆ จะต้องเป็นสมาชิกของคลาส
บรรทัดที่ 5 เป็นนิยามเมธอด Add()
โปรดสังเกตว่าผู้เขียนได้กำหนดให้เมธอดนี้มีชนิดเป็น static
ซึ่งมีผลให้มันเป็นสมาชิกของคลาส (ไม่ใช่สมาชิกของออพเจ็กต์)
สาเหตุที่ทำเช่นนี้เพราะต้องการอำนวยความสะดวกให้โค้ดฝั่ง Main
สามารถเรียกใช้เมธอดนี้ได้โดยไม่จำเป็นต้องสร้างออพเจ็กต์จากคลาส test1 เสียก่อน
ต่อไปมาดูตัวอย่างซอร์สโค้ดภาษาซีชาร์พส่วนนิยามฟังก์ชัน Add()
คำสั่งบรรทัด 1 ทำหน้าที่ระบุเนมสเปส
โปรดสังเกตว่าชื่อของเนมสเปสจะต้องตรงกันกับเนมสเปสของซอร์สโค้ดที่เรียกใช้ฟังก์ชัน Add()
ซึ่งในตัวอย่างนี้คือ Main() ที่มีเนมสเปสชื่อ csharp1
บรรทัดที่ 3 คือประกาศนิยามคลาส test1
สาเหตุที่ต้องประกาศนิยามคลาสเนื่องจากในภาษาซีชาร์พเราไม่สามารถเขียนฟังก์ชันหรือเมธอดไว้ลอย ๆ ได้
ฟังก์ชันหรือเมธอดใด ๆ จะต้องเป็นสมาชิกของคลาส
บรรทัดที่ 5 เป็นนิยามเมธอด Add()
โปรดสังเกตว่าผู้เขียนได้กำหนดให้เมธอดนี้มีชนิดเป็น static
ซึ่งมีผลให้มันเป็นสมาชิกของคลาส (ไม่ใช่สมาชิกของออพเจ็กต์)
สาเหตุที่ทำเช่นนี้เพราะต้องการอำนวยความสะดวกให้โค้ดฝั่ง Main
สามารถเรียกใช้เมธอดนี้ได้โดยไม่จำเป็นต้องสร้างออพเจ็กต์จากคลาส test1 เสียก่อน

คำอธิบายภาพ: ผลลัพธ์การทำงานของโปรแกรม บรรทัดที่เห็นเป็นเลข 3 คือผลจากการทำงานของโค้ด Main() บรรทัดที่ 9
และบรรทัดที่เห็นเป็นคำว่า End. คือผลจากการทำงานของโค้ดบรรทัดที่ 10
ไม่ต้องไล่ลำดับฟังก์ชัน
ในภาษาซีและซีพลัสพลัส การเขียนนิยามฟังก์ชันจะต้องใส่ไว้ในตำแหน่งก่อนหน้าโค้ดที่จะเรียกใช้งาน
แต่ในภาษาซีชาร์ฟจะใส่ไว้ก่อนหรือหลังก็ได้ ทำให้สะดวกในการจัดหมวดหมู่ของโค้ดภายในแต่ละซอร์สไฟล์
ในภาษาซีมาตรฐาน (C99 หรือ C11) กำหนดไว้ว่า
เราจะต้องใส่นิยามฟังก์ชันไว้ในตำแหน่งก่อนหน้าโค้ดที่จะเรียกใช้งาน
(หรือจะประกาศฟังก์ชันโปรโตไทป์ไว้ในเฮดเดอร์ไฟล์แทนก็ได้)
การทำแบบนี้ไม่สะดวกนัก เพราะหากต้องการแก้ไขโค้ด
เช่น เปลี่ยนชื่อฟังก์ชัน หรือเปลี่ยนซิกเนเจอร์ของฟังก์ชัน (ค่าส่งกลับและพารามิเตอร์)
เราจะต้องไม่ลืมที่จะแก้ประกาศฟังก์ชันโปรโตไทป์ให้ตรงกันด้วย
ภาษาซีชาร์พแก้ปัญหานี้โดยยอมให้เราใส่นิยามฟังก์ชันไว้ก่อนหน้าหรือหลังโค้ดที่จะเรียกใช้งานก็ได้
และไม่ต้องประกาศฟังก์ชันโปรโตไทป์เอาไว้ก่อน คอมไพเลอร์จะฉลาดพอที่จะตรวจสอบฟังก์ชันซิกเนเจอร์ได้เอง
แม้ว่าฟังก์ชันที่ถูกเรียกใช้จะอยู่คนละซอร์สไฟล์หรือคนละแอสเซมบลี้เลยก็ตาม
และบรรทัดที่เห็นเป็นคำว่า End. คือผลจากการทำงานของโค้ดบรรทัดที่ 10
ไม่ต้องไล่ลำดับฟังก์ชัน
ในภาษาซีและซีพลัสพลัส การเขียนนิยามฟังก์ชันจะต้องใส่ไว้ในตำแหน่งก่อนหน้าโค้ดที่จะเรียกใช้งาน
แต่ในภาษาซีชาร์ฟจะใส่ไว้ก่อนหรือหลังก็ได้ ทำให้สะดวกในการจัดหมวดหมู่ของโค้ดภายในแต่ละซอร์สไฟล์
ในภาษาซีมาตรฐาน (C99 หรือ C11) กำหนดไว้ว่า
เราจะต้องใส่นิยามฟังก์ชันไว้ในตำแหน่งก่อนหน้าโค้ดที่จะเรียกใช้งาน
(หรือจะประกาศฟังก์ชันโปรโตไทป์ไว้ในเฮดเดอร์ไฟล์แทนก็ได้)
การทำแบบนี้ไม่สะดวกนัก เพราะหากต้องการแก้ไขโค้ด
เช่น เปลี่ยนชื่อฟังก์ชัน หรือเปลี่ยนซิกเนเจอร์ของฟังก์ชัน (ค่าส่งกลับและพารามิเตอร์)
เราจะต้องไม่ลืมที่จะแก้ประกาศฟังก์ชันโปรโตไทป์ให้ตรงกันด้วย
ภาษาซีชาร์พแก้ปัญหานี้โดยยอมให้เราใส่นิยามฟังก์ชันไว้ก่อนหน้าหรือหลังโค้ดที่จะเรียกใช้งานก็ได้
และไม่ต้องประกาศฟังก์ชันโปรโตไทป์เอาไว้ก่อน คอมไพเลอร์จะฉลาดพอที่จะตรวจสอบฟังก์ชันซิกเนเจอร์ได้เอง
แม้ว่าฟังก์ชันที่ถูกเรียกใช้จะอยู่คนละซอร์สไฟล์หรือคนละแอสเซมบลี้เลยก็ตาม

คำอธิบายภาพ: ตัวอย่างโค้ดภาษาซีที่แสดงให้เห็นว่าจะต้องใส่นิยามฟังก์ชันไว้ก่อนหน้าโค้ดที่ต้องการเรียกใช้
ในตัวอย่างโค้ดภาษาซีนี้มีฟังก์ชัน Main() ที่เรียกใช้ฟังก์ชัน add() และฟังก์ชัน sub() ที่บรรทัดที่ 11 และ 12 ตามลำดับ
โปรดสังเกตว่านิยามฟังก์ชัน add() อยู่ที่บรรทัด 3 ถึง 6
ซึ่งอยู่ก่อนหน้าโค้ดที่จะเรียกใช้มัน (คือฟังก์ชัน Main() ที่อยู่ระหว่างบรรทัดที่ 8 ถึง 14)
จึงไม่มีปัญหาอะไร แต่นิยามฟังก์ชัน sub ซึ่งอยู่ระหว่างบรรทัดที่ 16 ถึง 19
นั้นอยู่ในตำแหน่งใต้ฟังก์ชัน Main() การทำเช่นนี้เมื่อคอมไพล์โปรแกรม
คอมไพเลอร์จะแจ้งความผิดพลาดว่าหานิยามของฟังก์ชัน sub() ไม่พบ
ในตัวอย่างโค้ดภาษาซีนี้มีฟังก์ชัน Main() ที่เรียกใช้ฟังก์ชัน add() และฟังก์ชัน sub() ที่บรรทัดที่ 11 และ 12 ตามลำดับ
โปรดสังเกตว่านิยามฟังก์ชัน add() อยู่ที่บรรทัด 3 ถึง 6
ซึ่งอยู่ก่อนหน้าโค้ดที่จะเรียกใช้มัน (คือฟังก์ชัน Main() ที่อยู่ระหว่างบรรทัดที่ 8 ถึง 14)
จึงไม่มีปัญหาอะไร แต่นิยามฟังก์ชัน sub ซึ่งอยู่ระหว่างบรรทัดที่ 16 ถึง 19
นั้นอยู่ในตำแหน่งใต้ฟังก์ชัน Main() การทำเช่นนี้เมื่อคอมไพล์โปรแกรม
คอมไพเลอร์จะแจ้งความผิดพลาดว่าหานิยามของฟังก์ชัน sub() ไม่พบ
คำอธิบายภาพ: ตัวอย่างโค้ดภาษาซีชาร์พที่แสดงให้เห็นว่าเราสามารถใส่นิยามเมธอดไว้ก่อนหน้าหรือหลังโค้ดที่จะเรียกใช้ก็ได้
ในตัวอย่างโค้ดภาษาซีชาร์พนี้มีเมธอด Main() ที่เรียกใช้เมธอด Add()
และเมธอด Sub() ที่บรรทัดที่ 14 และ 15 ตามลำดับ
โปรดสังเกตว่านิยามฟังก์ชัน Add() อยู่ที่บรรทัด 7 ถึง 10 ซึ่งอยู่ก่อนหน้าโค้ดที่จะเรียกใช้มัน
(คือเมธอด Main() ที่อยู่ระหว่างบรรทัดที่ 12 ถึง 17) จึงไม่มีปัญหาอะไร
ส่วนนิยามเมธอด sub ซึ่งอยู่ระหว่างบรรทัดที่ 19 ถึง 22 นั้นแม้จะอยู่ในตำแหน่งใต้เมธอด Main()
เมื่อคอมไพล์โปรแกรมคอมไพเลอร์จะไม่แจ้งความผิดพลาดว่าหานิยามของเมธอด Sub() ไม่พบอย่างในภาษาซี
แต่จะคอมไพล์ผ่านและรันได้เป็นปรกติ
ในตัวอย่างโค้ดภาษาซีชาร์พนี้มีเมธอด Main() ที่เรียกใช้เมธอด Add()
และเมธอด Sub() ที่บรรทัดที่ 14 และ 15 ตามลำดับ
โปรดสังเกตว่านิยามฟังก์ชัน Add() อยู่ที่บรรทัด 7 ถึง 10 ซึ่งอยู่ก่อนหน้าโค้ดที่จะเรียกใช้มัน
(คือเมธอด Main() ที่อยู่ระหว่างบรรทัดที่ 12 ถึง 17) จึงไม่มีปัญหาอะไร
ส่วนนิยามเมธอด sub ซึ่งอยู่ระหว่างบรรทัดที่ 19 ถึง 22 นั้นแม้จะอยู่ในตำแหน่งใต้เมธอด Main()
เมื่อคอมไพล์โปรแกรมคอมไพเลอร์จะไม่แจ้งความผิดพลาดว่าหานิยามของเมธอด Sub() ไม่พบอย่างในภาษาซี
แต่จะคอมไพล์ผ่านและรันได้เป็นปรกติ
คำอธิบายภาพ: ภาพแสดงผลลัพธ์การทำงานของโปรแกรมภาษาซีชาร์พที่เรียกใช้เมธอด Add() และเมธอด Sub()
เลข 3 ที่เห็นเกิดจากการทำงานของโค้ดบรรทัดที่ 14 เลข 57 เกิดจากการทำงานของโค้ดบรรทัดที่ 15
ไม่ต้องประกาศคลาสและฟังก์ชัน
ในภาษาซีพลัสพลัสมีข้อกำหนดให้ประกาศคลาสและฟังก์ชันไว้ก่อนหน้าโค้ดที่จะเรียกใช้
แต่ในภาษาซีชาร์พ เราสามารถอ้างถึงคลาส (คืออ้างถึงไทป์) ได้โดยไม่ต้องประกาศไว้ก่อนล่วงหน้า
(แต่ต้องมีนิยามอยู่ในเนมสเปสเดียวกัน)
และในทำนองเดียวกัน เราสามารถอ้างถึงฟังก์ชัน (เมธอด) ได้โดยไม่ต้องประกาศไว้ก่อนด้วย
เลข 3 ที่เห็นเกิดจากการทำงานของโค้ดบรรทัดที่ 14 เลข 57 เกิดจากการทำงานของโค้ดบรรทัดที่ 15
ไม่ต้องประกาศคลาสและฟังก์ชัน
ในภาษาซีพลัสพลัสมีข้อกำหนดให้ประกาศคลาสและฟังก์ชันไว้ก่อนหน้าโค้ดที่จะเรียกใช้
แต่ในภาษาซีชาร์พ เราสามารถอ้างถึงคลาส (คืออ้างถึงไทป์) ได้โดยไม่ต้องประกาศไว้ก่อนล่วงหน้า
(แต่ต้องมีนิยามอยู่ในเนมสเปสเดียวกัน)
และในทำนองเดียวกัน เราสามารถอ้างถึงฟังก์ชัน (เมธอด) ได้โดยไม่ต้องประกาศไว้ก่อนด้วย
คำอธิบายภาพ: ตัวอย่างโค้ดภาษาซีพลัสพลัสแสดงให้เห็นว่ามีข้อกำหนดให้ประกาศคลาสและฟังก์ชันไว้ก่อนหน้าโค้ดที่จะเรียกใช้
ในตัวอย่างโค้ดภาษาซีพลัสพลัส
บรรทัดที่ 7 ถึง 10 คือนิยามคลาส Matrix ที่ภายในอ้างถึงฟังก์ชัน f() และคลาส Vector
โดยที่นิยามของฟังก์ชัน f() และคลาส Vector อยู่ภายหลังจากนิยามของคลาส Matrix
การทำเช่นนี้จะมีผลให้เกิดการแจ้งความผิดพลาดตอนคอมไพล์
วิธีแก้ไขคือใส่ส่วนประกาศฟังก์ชัน f() และคลาส Vector ไว้ในตำแหน่งก่อนคลาส Matrix
(คือที่บรรทัด 4 และ 5 ตามลำดับ)
ในตัวอย่างโค้ดภาษาซีพลัสพลัส
บรรทัดที่ 7 ถึง 10 คือนิยามคลาส Matrix ที่ภายในอ้างถึงฟังก์ชัน f() และคลาส Vector
โดยที่นิยามของฟังก์ชัน f() และคลาส Vector อยู่ภายหลังจากนิยามของคลาส Matrix
การทำเช่นนี้จะมีผลให้เกิดการแจ้งความผิดพลาดตอนคอมไพล์
วิธีแก้ไขคือใส่ส่วนประกาศฟังก์ชัน f() และคลาส Vector ไว้ในตำแหน่งก่อนคลาส Matrix
(คือที่บรรทัด 4 และ 5 ตามลำดับ)
คำอธิบายภาพ: ตัวอย่างโค้ดภาษาซีชาร์พแสดงให้เห็นว่าไม่มีข้อกำหนดให้ประกาศคลาสและฟังก์ชัน (เมธอด) ไว้ก่อนหน้าโค้ดที่จะเรียกใช้
ในตัวอย่างโค้ดภาษาซีชาร์พบรรทัดที่ 11 ถึง 16 คือนิยามคลาสที่ภายในอ้างถึงเมธอด Fun()
และคลาส Vector และตัวมันเองคือ Matrix โดยที่นิยามของเมธอด fun()
และคลาส Vector อยู่ภายหลังจากนิยามของคลาส Matrix
การทำเช่นนี้ไม่มีปัญหาอะไรเลย โปรแกรมสามารถคอมไพล์และรันได้โดยไม่เกิดความผิดพลาดใด ๆ
หมดปัญหาการอ้างเป็นวงรอบ
การขึ้นแก่กันเป็นวงรอบหรือเป็นงูกินหางหรือเซอร์คูลาดีเพนเดนซี (Circular Dependency)
เป็นปัญหาที่สร้างความเดือนร้อนรำคาญและเป็นบักที่กวนใจนักเขียนโค้ดภาษาซีพลัสพลัสอยู่เนือง ๆ
ปัญหานี้เกิดจากการมีโมดูลสองโมดูล (หรือมากกว่า) อ้างถึงหรือขึ้นแก่กันโดยตรง (หรือโดยอ้อม)
ทำให้เกิดภาวะรีเคอร์ซีฟ
ในตัวอย่างโค้ดภาษาซีชาร์พบรรทัดที่ 11 ถึง 16 คือนิยามคลาสที่ภายในอ้างถึงเมธอด Fun()
และคลาส Vector และตัวมันเองคือ Matrix โดยที่นิยามของเมธอด fun()
และคลาส Vector อยู่ภายหลังจากนิยามของคลาส Matrix
การทำเช่นนี้ไม่มีปัญหาอะไรเลย โปรแกรมสามารถคอมไพล์และรันได้โดยไม่เกิดความผิดพลาดใด ๆ
หมดปัญหาการอ้างเป็นวงรอบ
การขึ้นแก่กันเป็นวงรอบหรือเป็นงูกินหางหรือเซอร์คูลาดีเพนเดนซี (Circular Dependency)
เป็นปัญหาที่สร้างความเดือนร้อนรำคาญและเป็นบักที่กวนใจนักเขียนโค้ดภาษาซีพลัสพลัสอยู่เนือง ๆ
ปัญหานี้เกิดจากการมีโมดูลสองโมดูล (หรือมากกว่า) อ้างถึงหรือขึ้นแก่กันโดยตรง (หรือโดยอ้อม)
ทำให้เกิดภาวะรีเคอร์ซีฟ
คำอธิบายภาพ: ตัวอย่างโค้ดภาษาซีพลัสพลัสที่มีปัญหาการขึ้นแก่กันเป็นวงรอบ
ในตัวอย่างโค้ดภาษาซีพลัสพลัสมีซอร์สโค้ดสามไฟล์ ไฟล์หลักคือ main.cpp
และเฮดเดอร์ไฟล์สองไฟล์คือ Foo.h และ Bar.h
โปรดสังเกตว่าภายใน Foo.h มีนิยามคลาส Foo ที่ภายในนั้นอ้างถึงคลาส Bar
และในทำนองเดียวกัน Foo.h มีนิยามคลาส Foo ที่อ้างถึงคลาส Bar
ปัญหาจะเกิดขึ้นเมื่อคอมไพเลอร์พบโค้ดบรรทัดที่ 16 ที่อ้างถึงคลาส Foo
เพราะคอมไพเลอร์จะต้องจองเนื้อที่ในหน่วยความจำเพื่อเก็บออพเจ็กต์ Foo
และขนาดของการจองเนื้อที่ดังกล่าวนี้จะขึ้นกับขนาดของ Bar
ซึ่งขึ้นกับ Foo เป็นเช่นนี้ไปเรื่อย ๆ กระบวนการจองเนื้อที่จะวนซ้ำเป็นอนันต์
ในตัวอย่างโค้ดภาษาซีพลัสพลัสมีซอร์สโค้ดสามไฟล์ ไฟล์หลักคือ main.cpp
และเฮดเดอร์ไฟล์สองไฟล์คือ Foo.h และ Bar.h
โปรดสังเกตว่าภายใน Foo.h มีนิยามคลาส Foo ที่ภายในนั้นอ้างถึงคลาส Bar
และในทำนองเดียวกัน Foo.h มีนิยามคลาส Foo ที่อ้างถึงคลาส Bar
ปัญหาจะเกิดขึ้นเมื่อคอมไพเลอร์พบโค้ดบรรทัดที่ 16 ที่อ้างถึงคลาส Foo
เพราะคอมไพเลอร์จะต้องจองเนื้อที่ในหน่วยความจำเพื่อเก็บออพเจ็กต์ Foo
และขนาดของการจองเนื้อที่ดังกล่าวนี้จะขึ้นกับขนาดของ Bar
ซึ่งขึ้นกับ Foo เป็นเช่นนี้ไปเรื่อย ๆ กระบวนการจองเนื้อที่จะวนซ้ำเป็นอนันต์
คำอธิบายภาพ: ตัวอย่างโค้ดภาษาซีชาร์พที่ไม่มีปัญหาการขึ้นแก่กันเป็นวงรอบ
ในตัวอย่างโค้ดภาษาชีชาร์พจะเห็นว่ามีนิยามคลาส Foo ที่บรรทัด 7 ถึง 9 นิยามคลาส Bar ที่บรรทัด 11 ถึง 14
และภายในคลาส Foo บรรทัดที่ 9 อ้างถึงคลาส Bar และภายในคลาส Bar บรรทัดที่ 13 ก็อ้างถึงคลาส Foo
และในเมธอด Main() บรรทัดที่ 17 ก็อ้างถึงคลาส Foo แต่คอมไพเลอร์ภาษาซีชาร์พสามารถคอมไพล์ผ่าน
และรันได้โดยไม่เกิดกระบวนการจองเนื้อที่ซ้ำเป็นอนันต์เหมือนอย่างคอมไพเลอร์ภาษาซีพลัสพลัส
ตัวแปรและเมธอดต้องมีเจ้าของ
จุดเด่นอีกอย่างหนึ่งของภาษาซีชาร์พคือเราจะประกาศตัวแปรและเมธอดไว้อย่างลอย ๆ
โดยไม่มีที่มาที่ไปหรือพวกโกบัลวาริเอเบิ้ล (Global Variable) ไม่ได้
ตัวแปรและเมธอดจะต้องเป็นสมาชิกของคลาสเท่านั้น
ขณะที่ภาษาซีและภาษาซีพลัสพลัสท่านสามาถใส่ตัวแปรและเมธอดไว้ตรงไหนในซอร์สไฟล์ก็ได้
ซึ่งเป็นวิธีเขียนโค้ดที่ไม่ดี เพราะจะทำให้เกิดปัญหาประเภทที่หาสาเหตุไม่พบและดีบักได้ยาก
ในตัวอย่างโค้ดภาษาชีชาร์พจะเห็นว่ามีนิยามคลาส Foo ที่บรรทัด 7 ถึง 9 นิยามคลาส Bar ที่บรรทัด 11 ถึง 14
และภายในคลาส Foo บรรทัดที่ 9 อ้างถึงคลาส Bar และภายในคลาส Bar บรรทัดที่ 13 ก็อ้างถึงคลาส Foo
และในเมธอด Main() บรรทัดที่ 17 ก็อ้างถึงคลาส Foo แต่คอมไพเลอร์ภาษาซีชาร์พสามารถคอมไพล์ผ่าน
และรันได้โดยไม่เกิดกระบวนการจองเนื้อที่ซ้ำเป็นอนันต์เหมือนอย่างคอมไพเลอร์ภาษาซีพลัสพลัส
ตัวแปรและเมธอดต้องมีเจ้าของ
จุดเด่นอีกอย่างหนึ่งของภาษาซีชาร์พคือเราจะประกาศตัวแปรและเมธอดไว้อย่างลอย ๆ
โดยไม่มีที่มาที่ไปหรือพวกโกบัลวาริเอเบิ้ล (Global Variable) ไม่ได้
ตัวแปรและเมธอดจะต้องเป็นสมาชิกของคลาสเท่านั้น
ขณะที่ภาษาซีและภาษาซีพลัสพลัสท่านสามาถใส่ตัวแปรและเมธอดไว้ตรงไหนในซอร์สไฟล์ก็ได้
ซึ่งเป็นวิธีเขียนโค้ดที่ไม่ดี เพราะจะทำให้เกิดปัญหาประเภทที่หาสาเหตุไม่พบและดีบักได้ยาก
คำอธิบายภาพ: ตัวอย่างโค้ดภาษาซีพลัสพลัสที่ประกาศตัวแปรและฟังก์ชันไว้ลอย ๆ ไม่มีที่มาที่ไป
ในตัวอย่างโค้ดภาษาซีพลัสพลัสบรรทัดที่ 1 ประกาศตัวแปร i ไว้ลอย ๆ ไม่ได้อยู่ในคลาสใด
และในบรรทัดที่ 3 ถึง 5 คือนิยามฟังก์ชัน add() ที่ประกาศไว้ลอย ๆ ไม่ได้เป็นสมาชิกของคลาสเช่นกัน
แต่โค้ดในบรรทัดที่ 8 และ 9 สามารถเรียกใช้หรืออ้างถึงตัวแปร และฟังก์ชันที่กล่าวมาได้โดยไม่มีปัญหา
และโปรแกรมนี้คอมไพล์และรันได้อย่างไม่มีความผิดพลาด แต่เป็นวิธีการเขียนโปรแกรมที่ไม่ดีนัก
และผิดหลักการเขียนโปรแกรมแบบวัตถุวิธี (Object Oriented Programming)
ในตัวอย่างโค้ดภาษาซีพลัสพลัสบรรทัดที่ 1 ประกาศตัวแปร i ไว้ลอย ๆ ไม่ได้อยู่ในคลาสใด
และในบรรทัดที่ 3 ถึง 5 คือนิยามฟังก์ชัน add() ที่ประกาศไว้ลอย ๆ ไม่ได้เป็นสมาชิกของคลาสเช่นกัน
แต่โค้ดในบรรทัดที่ 8 และ 9 สามารถเรียกใช้หรืออ้างถึงตัวแปร และฟังก์ชันที่กล่าวมาได้โดยไม่มีปัญหา
และโปรแกรมนี้คอมไพล์และรันได้อย่างไม่มีความผิดพลาด แต่เป็นวิธีการเขียนโปรแกรมที่ไม่ดีนัก
และผิดหลักการเขียนโปรแกรมแบบวัตถุวิธี (Object Oriented Programming)
คำอธิบายภาพ: ตัวอย่างโค้ดภาษาซีชาร์พแสดงการสร้างตัวแปรและเมธอดแบบโกบัลโดยอาศัยสแตติกคลาส
ในตัวอย่างโค้ดภาษาซีชาร์พจะเห็นว่ามีนิยามคลาสสองคลาส คือคลาส csharp 1 ที่อยู่ระหว่างบรรทัดที่ 3 ถึง 16
นี่คือคลาสหลักที่มีเมธอด Main() ถัดไปเป็นคลาส Util ซึ่งมีนิยามอยู่ระหว่างบรรทัดที่ 16 ถึง 24
อันเป็นคลาสที่เราจะใส่ตัวแปรและเมธอดแบบโกบัลที่สามารถเรียกใช้งานจากที่ไหนก็ได้
โปรดสังเกตว่าการประกาศตัวแปร id ในบรรทัดที่ 18 ได้ถูกกำหนดให้มีภาวะเป็น public static
การทำเช่นนี้ทำให้มันเป็นตัวแปรของคลาส (ไม่ใช่ของออพเจ็กต์)
การอ้างถึงหรือเรียกใช้งานจึงสามารถทำได้โดยตรง (ไม่ต้องสร้างออพเจ็กต์ก่อน) อย่างที่เห็นในบรรทัดที่ 9
และหากมีโค้ดในเมธอดในคลาสอื่น ๆ เรียกใช้งานตัวแปร id นี้ จะได้รับค่าเดียวกัน
และถ้ามันเปลี่ยนแปลงค่าของ id โค้ดบรรทัดที่ 9 ก็จะได้รับค่าที่ถูกเปลี่ยนไปแล้วนั้นด้วย
เพราะเป็นการอ้างถึงหน่วยเก็บข้อมูลชุดเดียวกัน
การตัดสินใจด้วยบูลีน
ในภาษาซีและภาษาซีพลัสพลัสนิพจน์เพื่อการตัดสินใจหรือคอนดิชันเอ็กซ์เพรสชัน (Condition Expression)
เราสามาถใช้นิพจน์คณิตศาสตร์ (Arithmetic Expression) หรือนิพจน์บูลีน (Boolean Expression) อย่างใดอย่างหนึ่งสลับกันก็ได้
ลักษณะเช่นนี้สร้างความปวดเศียรเวียนเกล้าให้กับโปรแกรมเมอร์มาทุกยุค
เพราะทำให้การไล่โค้ดและการดีบักเนืองแน่นไปด้วยขวากหนามและหลุมพราง
เพื่อตัดปัญหาเหล่านี้ ผู้ออกแบบภาษาซีชาร์พจึงกำหนดให้ทุก ๆ คอนดิชันเอ็กเพรสชันจะต้องเป็นนิพจน์บูลีนเท่านั้น
ในตัวอย่างโค้ดภาษาซีชาร์พจะเห็นว่ามีนิยามคลาสสองคลาส คือคลาส csharp 1 ที่อยู่ระหว่างบรรทัดที่ 3 ถึง 16
นี่คือคลาสหลักที่มีเมธอด Main() ถัดไปเป็นคลาส Util ซึ่งมีนิยามอยู่ระหว่างบรรทัดที่ 16 ถึง 24
อันเป็นคลาสที่เราจะใส่ตัวแปรและเมธอดแบบโกบัลที่สามารถเรียกใช้งานจากที่ไหนก็ได้
โปรดสังเกตว่าการประกาศตัวแปร id ในบรรทัดที่ 18 ได้ถูกกำหนดให้มีภาวะเป็น public static
การทำเช่นนี้ทำให้มันเป็นตัวแปรของคลาส (ไม่ใช่ของออพเจ็กต์)
การอ้างถึงหรือเรียกใช้งานจึงสามารถทำได้โดยตรง (ไม่ต้องสร้างออพเจ็กต์ก่อน) อย่างที่เห็นในบรรทัดที่ 9
และหากมีโค้ดในเมธอดในคลาสอื่น ๆ เรียกใช้งานตัวแปร id นี้ จะได้รับค่าเดียวกัน
และถ้ามันเปลี่ยนแปลงค่าของ id โค้ดบรรทัดที่ 9 ก็จะได้รับค่าที่ถูกเปลี่ยนไปแล้วนั้นด้วย
เพราะเป็นการอ้างถึงหน่วยเก็บข้อมูลชุดเดียวกัน
การตัดสินใจด้วยบูลีน
ในภาษาซีและภาษาซีพลัสพลัสนิพจน์เพื่อการตัดสินใจหรือคอนดิชันเอ็กซ์เพรสชัน (Condition Expression)
เราสามาถใช้นิพจน์คณิตศาสตร์ (Arithmetic Expression) หรือนิพจน์บูลีน (Boolean Expression) อย่างใดอย่างหนึ่งสลับกันก็ได้
ลักษณะเช่นนี้สร้างความปวดเศียรเวียนเกล้าให้กับโปรแกรมเมอร์มาทุกยุค
เพราะทำให้การไล่โค้ดและการดีบักเนืองแน่นไปด้วยขวากหนามและหลุมพราง
เพื่อตัดปัญหาเหล่านี้ ผู้ออกแบบภาษาซีชาร์พจึงกำหนดให้ทุก ๆ คอนดิชันเอ็กเพรสชันจะต้องเป็นนิพจน์บูลีนเท่านั้น
คำอธิบายภาพ: ตัวอย่างโค้ดภาษาซีพลัสพลัสที่ใช้คอนดิชันเอ็กซ์เพรสชันเป็นนิพจน์คณิตศาสตร์และบูลีนปนกัน
คำอธิบายภาพ: ตัวอย่างโค้ดภาษาซีชาร์พแสดงการเขียนคอนดิชันเอ็กซ์เพรสชันเป็นนิพจน์คณิตศาสตร์และบูลีนปนกันซึ่งทำให้เกิดความผิดพลาดตอนคอมไพล์
ในตัวอย่างโค้ดภาษาซีพลัสพลัสโค้ดที่เป็นคอนดิชันเอ็กซ์เพรสชันมีอยู่สองแห่ง คือบรรทัดที่ 10 และ 15
โปรดสังเกตว่า
บรรทัดที่ 10 ในวงเล็บ if() คือตัวแปร is_a_car ซึ่งเป็นตัวแปรแบบบูลีน
นี่คือตัวอย่างการเขียนคอนดิชันเอ็กซ์เพรสชันที่ดี เพราะเป็นเอ็กซ์เพรสชันที่ให้ผลลัพธ์เป็นบูลีน (คือจริงหรือเท็จเท่านั้น)
ส่วนบรรทัดที่ 15 ในวงเล็บ if() คือตัวแปร salary
ซึ่งเป็นตัวแปรแบบเลขจำนวนเต็มโปรแกรมนี้ก็ยังคอมไพล์ผ่านและทำงานได้
แต่จะสร้างความงุนงงสงสัยให้แก่ผู้อ่านโค้ดว่าคำสั่ง if จะมีผลให้โค้ดบรรทัดที่ 16 หรือ 18 ทำงานกันแน่และเพราะอะไร
โปรดสังเกตในตัวอย่างโค้ดภาษาซีชาร์พบรรทัดที่ 17
จะเห็นว่าการนำตัวแปรที่มีชนิดข้อมูลเป็น int มาใส่ในวงเล็บของคำสั่ง if
เท่ากับเป็นการเขียนคอนดิชันเอ็กซ์เพรสชันที่จะให้ค่าเป็นตัวเลข
การทำเช่นนี้ในภาษาซีชาร์พทำไม่ได้ โปรแกรมจะคอมไพล์ไม่ผ่าน
เพราะในภาษาซีชาร์พคอนดิชันเอ็กซ์เพรสชันจะต้องให้ค่าเป็นบูลีนอย่างบรรทัดที่ 12 เท่านั้น
ซึ่งเป็นการดีเพราะจะทำให้โค้ดสะอาดปราศจากความคลุมเครือ
จบตอนที่ 2 แต่เพียงเท่านี้ก่อนนะครับ
ในตัวอย่างโค้ดภาษาซีพลัสพลัสโค้ดที่เป็นคอนดิชันเอ็กซ์เพรสชันมีอยู่สองแห่ง คือบรรทัดที่ 10 และ 15
โปรดสังเกตว่า
บรรทัดที่ 10 ในวงเล็บ if() คือตัวแปร is_a_car ซึ่งเป็นตัวแปรแบบบูลีน
นี่คือตัวอย่างการเขียนคอนดิชันเอ็กซ์เพรสชันที่ดี เพราะเป็นเอ็กซ์เพรสชันที่ให้ผลลัพธ์เป็นบูลีน (คือจริงหรือเท็จเท่านั้น)
ส่วนบรรทัดที่ 15 ในวงเล็บ if() คือตัวแปร salary
ซึ่งเป็นตัวแปรแบบเลขจำนวนเต็มโปรแกรมนี้ก็ยังคอมไพล์ผ่านและทำงานได้
แต่จะสร้างความงุนงงสงสัยให้แก่ผู้อ่านโค้ดว่าคำสั่ง if จะมีผลให้โค้ดบรรทัดที่ 16 หรือ 18 ทำงานกันแน่และเพราะอะไร
โปรดสังเกตในตัวอย่างโค้ดภาษาซีชาร์พบรรทัดที่ 17
จะเห็นว่าการนำตัวแปรที่มีชนิดข้อมูลเป็น int มาใส่ในวงเล็บของคำสั่ง if
เท่ากับเป็นการเขียนคอนดิชันเอ็กซ์เพรสชันที่จะให้ค่าเป็นตัวเลข
การทำเช่นนี้ในภาษาซีชาร์พทำไม่ได้ โปรแกรมจะคอมไพล์ไม่ผ่าน
เพราะในภาษาซีชาร์พคอนดิชันเอ็กซ์เพรสชันจะต้องให้ค่าเป็นบูลีนอย่างบรรทัดที่ 12 เท่านั้น
ซึ่งเป็นการดีเพราะจะทำให้โค้ดสะอาดปราศจากความคลุมเครือ
จบตอนที่ 2 แต่เพียงเท่านี้ก่อนนะครับ