มีอะไรใหม่ใน .NET Core 2 และ C# 7 : การ Deconstruct Tuple และ Type อื่น ๆ

มีอะไรใหม่ใน .NET Core 2 และ C# 7 : การ Deconstruct Tuple และ Type อื่น ๆ
ภาษาC# 7.0 ขึ้นไปสนับสนุนการประกาศตัวแปรแบบ Discard ซึ่งเป็นตัวแปรแบบเขียนได้เท่านั้น (read-only)
โดยที่ท่านจะประกาศตัวแปรแบบนี้กี่ตัวก็ได้ แต่ทุกตัวจะมีชื่อเดียวกันหมดคือ _ (เครื่องหมายขีดเส้นใต้หรือ underscore)
ประโยชน์ของตัวแปรแบบ discard คือ การนำไปใช้กับ Tuple
เพราะ การรับค่าส่งกลับจาก method ที่ส่งค่ากลับเป็นTuple หรือ การเรียกใช้ method ที่มีพารามิเตอร์แบบ out
เราจะต้องประกาศตัวแปรไว้รับค่า ซึ่งบ่อยครั้งที่เราไม่ต้องการใช้ค่าจากตัวแปรเหล่านั้น แต่ก็จำต้องประกาศ ทำให้โค้ดรกรุงรังโดยเปล่าประโยชน์
โดยที่ท่านจะประกาศตัวแปรแบบนี้กี่ตัวก็ได้ แต่ทุกตัวจะมีชื่อเดียวกันหมดคือ _ (เครื่องหมายขีดเส้นใต้หรือ underscore)
ประโยชน์ของตัวแปรแบบ discard คือ การนำไปใช้กับ Tuple
เพราะ การรับค่าส่งกลับจาก method ที่ส่งค่ากลับเป็นTuple หรือ การเรียกใช้ method ที่มีพารามิเตอร์แบบ out
เราจะต้องประกาศตัวแปรไว้รับค่า ซึ่งบ่อยครั้งที่เราไม่ต้องการใช้ค่าจากตัวแปรเหล่านั้น แต่ก็จำต้องประกาศ ทำให้โค้ดรกรุงรังโดยเปล่าประโยชน์
โดยใช้ตัวแปรแบบ discard ท่านสามารถประกาศตัวแปรเพียงตัวเดียว แล้วนำไปใช้รับค่าส่งกลับทั้งหมดจาก method หรือนำไปใช้แทนที่ตัวแปร out ของ method พารามิเตอร์ได้ทุกตัว
การทำเช่นนี้มีผลให้ source code สะอาดเรียบร้อย อ่านเข้าใจได้งายขึ้น
การทำเช่นนี้มีผลให้ source code สะอาดเรียบร้อย อ่านเข้าใจได้งายขึ้น
เราสามารถใช้ตัวแปรแบบ discard ได้ในกรณีต่าง ๆ ดังต่อไปนี้
- เมื่อถอด (deconstructing) Tuple หรือ Type ที่ผู้ใช้กำหนดใด ๆ
- เมื่อเรียกหา method ที่มีพารามิเตอร์แบบ out
- เมื่อกระทำการเปรียบเทียบรูปแบบด้วยคำสั่ง is และ switch
- ใช้เพื่อตัวระบุตัวแปรที่ไม่ต้องการใช้งาน

จากรูปข้างบน
บรรทัด 13 ถึง 33 คือนิยาม method QueryCityDataForYears ที่มีค่าส่งกลับเป็นข้อมูลสองปีของเมือง ๆ หนึ่ง โดยอยู่ในรูปของ Tuple ที่มีสมาชิกจำนวน 6 ตัว
บรรทัดที่ 8 แสดงตัวอย่างการเรียกใช้งานmethodนี้
โปรดสังเกตวิธีรับค่าส่งกลับ ในตัวอย่างนี้สมมติว่า เราต้องการเพียงจำนวนประชากรเท่านั้น ไม่สนใจค่าส่งกลับอื่น ๆ
นั่นคือเราไม่ต้องการค่าส่งกลับตัวที่ 1, 2, 3 และ 5 แต่ต้องการตัวที่ 4 และ 6 (ที่เป็นจำนวนประชากร)
แต่ถึงแม้จะไม่ต้องการเราก็จำเป็นต้องใส่ตัวแปรไว้รับค่าให้ครบ 6 ตัว
ดังนั้นเพื่อให้โค้ดกระชับเราจึงใช้ตัวแปรแบบ discard ( _ ) ใส่ไว้ในตำแหน่งที่ 1, 2, 3 และ 5 เพื่อให้ได้ Tuple ที่มีครบ 6 หน่วย
บรรทัด 13 ถึง 33 คือนิยาม method QueryCityDataForYears ที่มีค่าส่งกลับเป็นข้อมูลสองปีของเมือง ๆ หนึ่ง โดยอยู่ในรูปของ Tuple ที่มีสมาชิกจำนวน 6 ตัว
บรรทัดที่ 8 แสดงตัวอย่างการเรียกใช้งานmethodนี้
โปรดสังเกตวิธีรับค่าส่งกลับ ในตัวอย่างนี้สมมติว่า เราต้องการเพียงจำนวนประชากรเท่านั้น ไม่สนใจค่าส่งกลับอื่น ๆ
นั่นคือเราไม่ต้องการค่าส่งกลับตัวที่ 1, 2, 3 และ 5 แต่ต้องการตัวที่ 4 และ 6 (ที่เป็นจำนวนประชากร)
แต่ถึงแม้จะไม่ต้องการเราก็จำเป็นต้องใส่ตัวแปรไว้รับค่าให้ครบ 6 ตัว
ดังนั้นเพื่อให้โค้ดกระชับเราจึงใช้ตัวแปรแบบ discard ( _ ) ใส่ไว้ในตำแหน่งที่ 1, 2, 3 และ 5 เพื่อให้ได้ Tuple ที่มีครบ 6 หน่วย
การถอด Tuple และ Type อื่น ๆ
นอกจากตัวแปรแบบ discard แล้วในภาษา C# 7.0 ยังมีคุณสมบัติใหม่ที่อำนวยความสะดวกให้การทำงานกับข้อมูลเป็นชุดจาก Tuple หรือ Type อื่น ๆ ทำได้ง่ายขึ้น เรียกว่าคุณสมบัติ “การถอด” (Deconstructing ต่อไปจะเรียก “Deconstruct”)
หากไม่ใช้ Deconstruct เมื่อต้องการรับค่าจาก method ที่ส่งค่ากลับมาเป็น Tuple หลาย ๆ ค่า หรือ
รับค่าหลาย ๆ ค่าจาก object เราจะต้องประกาศตัวแปรหลาย ๆ ตัวเพื่อใช้เก็บค่าแต่ละค่า
หากไม่ใช้ Deconstruct เมื่อต้องการรับค่าจาก method ที่ส่งค่ากลับมาเป็น Tuple หลาย ๆ ค่า หรือ
รับค่าหลาย ๆ ค่าจาก object เราจะต้องประกาศตัวแปรหลาย ๆ ตัวเพื่อใช้เก็บค่าแต่ละค่า

บรรทัดที่ 21-28 คือ ตัวอย่าง Method QueryCityData ที่ส่งค่ากลับเป็นทูเพิลที่มีค่าอยู่สามค่า (ชื่อเมือง, จำนวนประชากรและขนาดของเมือง) ในวิธีเก่า (ที่ไม่ได้ใช้ Deconstruct)
เราจะต้องรับค่าด้วยตัวแปรแบบทูเพิล (บรรทัด 13) จากนั้นต้องประกาศตัวแปรสามตัวเพื่อดึงค่าจากทูเพิลมาเก็บ (บรรทัด 15-17)
การเขียนโค้ดวิธีนี้ไม่ค่อยดีเพราะรุงรังยืดเยื้อ source code รกไปด้วยประกาศ field หรือ property ตามจำนวนค่าที่จะรับ
เราจะต้องรับค่าด้วยตัวแปรแบบทูเพิล (บรรทัด 13) จากนั้นต้องประกาศตัวแปรสามตัวเพื่อดึงค่าจากทูเพิลมาเก็บ (บรรทัด 15-17)
การเขียนโค้ดวิธีนี้ไม่ค่อยดีเพราะรุงรังยืดเยื้อ source code รกไปด้วยประกาศ field หรือ property ตามจำนวนค่าที่จะรับ
เริ่มใน C# 7.0 เราสามารถทดแทนการเขียนโค้ดแบบเก่า ด้วย Deconstruct
ซึ่งเป็นวิธีใหม่ที่ช่วยให้เขียนโค้ดได้กะทัดรัดกว่า สามารถเขียนสั้น ๆ เพียงบรรทัดเดียว ไม่ต้องประกาศ field หรือ property ตามจำนวนค่าที่จะรับ
เราเพียงกำหนดตัวรับค่าตามรายการของ Tuple เมื่อใช้รับค่าจาก Tuple และกำหนดตัวรับค่าตามจำนวนตัวแปรเมื่อใช้รับค่าจาก object
ซึ่งเป็นวิธีใหม่ที่ช่วยให้เขียนโค้ดได้กะทัดรัดกว่า สามารถเขียนสั้น ๆ เพียงบรรทัดเดียว ไม่ต้องประกาศ field หรือ property ตามจำนวนค่าที่จะรับ
เราเพียงกำหนดตัวรับค่าตามรายการของ Tuple เมื่อใช้รับค่าจาก Tuple และกำหนดตัวรับค่าตามจำนวนตัวแปรเมื่อใช้รับค่าจาก object
คุณสมบัติ Decontruct
คุณสมบัติ Decontruct เป็นคุณสมบัติใหม่ที่ฝังอยู่ภายในภาษา C# สามารถเรียกใช้ได้โดยไม่ต้องอ้างถึงอะไรก่อน
ช่วยให้เราถอดค่าทั้งหมดจาก Tuple ได้ภายในบรรทัดคำสั่งเดียว หน้าตาของ Systax คล้ายการประกาศ Tuple คือใส่คำสั่ง var ตามด้วยวงเล็บ
ภายในวงเล็บเป็นรายการของตัวแปรที่จะเก็บค่าที่ต้องการถอดจาก Tuple
ช่วยให้เราถอดค่าทั้งหมดจาก Tuple ได้ภายในบรรทัดคำสั่งเดียว หน้าตาของ Systax คล้ายการประกาศ Tuple คือใส่คำสั่ง var ตามด้วยวงเล็บ
ภายในวงเล็บเป็นรายการของตัวแปรที่จะเก็บค่าที่ต้องการถอดจาก Tuple

บรรทัดที่ 4 เราต้องการถอดค่าจาก Method contact.GetAddressInfo()
ซึ่งเป็น method ที่มีค่าส่งกลับเป็น Tuple ประกอบด้วยค่า 4 ค่า คือ ชื่อ ที่อยู่ เมืองและรหัสไปรษณีย์
ทางขวามือเราเขียนตัว decontruct โดยใช้คำสั่ง var ตามด้วยวงเล็บ
ในวงเล็บเราประกาศตัวแปร 4 ตัว เรียงตามลำดับข้อมูลส่งกลับจาก Tuple
เราสามารถเขียนได้โดยไม่ต้องสนใจกับชนิดข้อมูล เพราะตัวแปลภาษาจะกำหนดชนิดข้อมูลให้สมพงศ์กับค่าส่งกลับเองโดยอัตโนมัติ
ซึ่งเป็น method ที่มีค่าส่งกลับเป็น Tuple ประกอบด้วยค่า 4 ค่า คือ ชื่อ ที่อยู่ เมืองและรหัสไปรษณีย์
ทางขวามือเราเขียนตัว decontruct โดยใช้คำสั่ง var ตามด้วยวงเล็บ
ในวงเล็บเราประกาศตัวแปร 4 ตัว เรียงตามลำดับข้อมูลส่งกลับจาก Tuple
เราสามารถเขียนได้โดยไม่ต้องสนใจกับชนิดข้อมูล เพราะตัวแปลภาษาจะกำหนดชนิดข้อมูลให้สมพงศ์กับค่าส่งกลับเองโดยอัตโนมัติ
systax ของ Decontruct มี 3 แบบ
- แบบที่ 1 คืออย่างที่เห็นในบรรทัดที่ 9 เราไม่ใช้คำสั่ง var แต่จะกำหนดชนิดข้อมูลของตัวแปรแต่ละตัวเอาเอง
- แบบที่ 2 คืออย่างที่เห็นในบรรทัดที่ 16 เราใช้คำสั่ง var และใส่รายการตัวแปรโดยไม่กำหนดชนิดข้อมูล
- แบบที่ 3 คืออย่างที่เห็นในบรรทัดที่ 23 เราไม่ใช้คำสั่ง var ข้างหน้าวงเล็บ แต่จะกำหนดชนิดข้อมูลของตัวแปรบางตัวเอาเอง และ บางตัวแปรก็ใส่คำสั่ง var ไว้หน้าตัวแปรที่ไม่ต้องการระบุ Type
ในกรณีที่เราประกาศตัวแปรไว้แล้ว และต้องการใช้ตัวแปรเหล่านั้นเพื่อเก็บค่าที่ถอดจาก Tuple ด้วยวิธี Decontruct
ก็สามารถทำได้ตามตัวอย่าง บรรทัด 28-37
โปรดทราบว่าการใส่รายการตัวแปรต้องใส่ให้ครบเท่ากันกับค่าที่จะถอด
ถ้าใส่ไม่ครบจะเกิด Compile Error CS8184
ก็สามารถทำได้ตามตัวอย่าง บรรทัด 28-37
โปรดทราบว่าการใส่รายการตัวแปรต้องใส่ให้ครบเท่ากันกับค่าที่จะถอด
ถ้าใส่ไม่ครบจะเกิด Compile Error CS8184
Decontruct Method
Method แบบใหม่ที่เริ่มมีในภาษา C# 7.0 คือ “Decontruct Method” (Deconstruct Method ต่อไปจะเรียก DM)
เราสามารถใส่นิยามของ DM ไว้ภายในคลาส ใน structure หรือใน Interface ก็ได้
เราสามารถใช้ DM เพื่อช่วยคัดกรองให้การถอดค่า Tuple หรือค่าที่เป็นชุดจาก Type ที่ผู้ใช้กำหนดขึ้นเอง เป็นการถอดค่าเพียงบางตัว (เซตย่อยของค่าทั้งหมด)
เราสามารถใส่นิยามของ DM ไว้ภายในคลาส ใน structure หรือใน Interface ก็ได้
เราสามารถใช้ DM เพื่อช่วยคัดกรองให้การถอดค่า Tuple หรือค่าที่เป็นชุดจาก Type ที่ผู้ใช้กำหนดขึ้นเอง เป็นการถอดค่าเพียงบางตัว (เซตย่อยของค่าทั้งหมด)

จากรูปข้างบน
บรรทัด 5-45 คือนิยามคลาส Person คลาสนี้มี “Auto-Implemented Property” 5 ตัว (บรรทัด 7-11)
เราต้องการกำหนดให้โค้ดนอกถอดค่าเหล่านี้ได้เพียงบางตัว 3 รูปแบบ จึงนิยาม DM และ overloadไว้ 3 แบบ คือ
แบบที่หนึ่งมีไว้เพื่อถอด 2 ค่า (บรรทัด 24-28)
แบบที่สองมีไว้เพื่อถอด 3 ค่า (บรรทัด 30-35)
และแบบที่สามมีไว้เพื่อถอด 4 ค่า (บรรทัด 37-43)
บรรทัด 5-45 คือนิยามคลาส Person คลาสนี้มี “Auto-Implemented Property” 5 ตัว (บรรทัด 7-11)
เราต้องการกำหนดให้โค้ดนอกถอดค่าเหล่านี้ได้เพียงบางตัว 3 รูปแบบ จึงนิยาม DM และ overloadไว้ 3 แบบ คือ
แบบที่หนึ่งมีไว้เพื่อถอด 2 ค่า (บรรทัด 24-28)
แบบที่สองมีไว้เพื่อถอด 3 ค่า (บรรทัด 30-35)
และแบบที่สามมีไว้เพื่อถอด 4 ค่า (บรรทัด 37-43)

ตัวอย่างโค้ดการนำคลาส Person ไปใช้สร้าง Object และ เรียกใช้ DM ของมัน
โค้ดบรรทัด 13 คือการเรียกใช้ DM แบบที่สามซึ่งมีไว้เพื่อถอดสี่ค่า
โปรดสังเกตว่าในตัวอย่างนี้สมมติว่าเราไม่สนค่า LastName และ State จึงใส่ตัวแปรแบบ discard ไว้ในตำแหน่งทั้งสองนั้น
จากบทความนี้ หวังว่า ท่านผู้อ่านจะเข้าใจการใช้งาน ตัวแปรแบบ discard รวมถึง วิธีการ deconstruct Tuple หรือ Type ที่ผู้ใช้กำหนดใด ๆ ได้ประมาณหนึ่งนะครับ
โค้ดบรรทัด 13 คือการเรียกใช้ DM แบบที่สามซึ่งมีไว้เพื่อถอดสี่ค่า
โปรดสังเกตว่าในตัวอย่างนี้สมมติว่าเราไม่สนค่า LastName และ State จึงใส่ตัวแปรแบบ discard ไว้ในตำแหน่งทั้งสองนั้น
จากบทความนี้ หวังว่า ท่านผู้อ่านจะเข้าใจการใช้งาน ตัวแปรแบบ discard รวมถึง วิธีการ deconstruct Tuple หรือ Type ที่ผู้ใช้กำหนดใด ๆ ได้ประมาณหนึ่งนะครับ