ไม่ได้อัพเดตสเปซเสียนานเลยครับ ช่วงนี้หน้าที่การงานรัดตัวเหลือเกินทั้งงานราษฎร์งานหลวง (มันเป็นข้อแก้ตัวที่ถึงแม้จะเอามารีไซเคิลใช้เรื่อยๆก็ยังดูดีนะครับ) สำหรับคราวนี้มีปัญหาเล็กๆแต่ก็น่ากวนใจสำหรับโปรแกรมเมอร์มือใหม่รวมถึงมือกลางเก่ากลางใหม่อย่างผมด้วย
ปัญหาที่ว่านี้ผมคิดว่าน่าจะเป็นปัญหาลำดับต้นๆปัญหาหนึ่งสำหรับนักพัฒนาที่เคยพัฒนาโปรแกรมด้วยภาษา VB มาก่อนและมาเริ่มต้นศึกษาการเขียนโปรแกรมด้วยภาษา C# ก็คือ การตรวจสอบชนิดของข้อมูล DateTime กับ Numeric ซึ่งใน VB จะมีฟังก์ชั่นสำหรับตรวจสอบชนิดของข้อมูลทั้งสองนี้และคืนค่ากลับมาเป็น Boolean (True/False) ฟังก์ชั่นที่กล่าวถึงนี้คือ IsDate() และ IsNumeric() ฟังก์ชั่นทั้งสองนี้มีใน VB มานานมากแล้วตั้งแต่สมัย VB4-VB5 นู่น (เก่ากว่านั้นผมไม่ทันครับ ;P) แต่…ใน C# ไม่ยักมี ดังนั้นเวลาที่เราต้องการแปลงชนิดข้อมูลไป-มาก็มักจะเกิดปัญหาบ่อยๆ จากการที่ไม่ได้ตรวจสอบชนิดของข้อมูลเสียก่อน
ที่ว่ามันกวนใจก็คือ เวลาจะแปลงชนิดข้อมูลแต่ละครั้งต้องมาเขียนตรวจสอบเหมือนเดิมๆทุกครั้ง บ่อยเข้าก็ชักจะหงุดหงิด เลยเกิดความคิดว่าน่าจะหาอะไรมาใช้แทนฟังก์ชั่นทั้งสองนั้นใน C# ได้มั่งนะ หาไปหามาก็ไปพบบทความของฝรั่งเค้า ซึ่งผมเห็นว่าน่าสนใจดี ที่เขียนชุดคำสั่งเลียนแบบการทำงานของ IsDate() และ IsNumeric() และผมก็ได้นำแนวคิดของเขาและโปรแกรมตัวอย่างมาลองเขียนและปรับปรุงนิดหน่อย และทดสอบดูแล้วเห็นว่าเข้าท่าดี ก็เลยเอามาแชร์กัน
สำหรับการเขียนฟังก์ชั่นเลียนแบบ IsDate() และ IsNumeric() นี้เรามีพระเอกอยู่หลายตัวครับ พระเอกของเราตัวแรกก็คือเมธอด Parse เมธอดนี้จะทำการแปลงค่า string ที่ส่งเข้ามาให้เป็นชนิดข้อมูลพื้นฐานของ .Net Framwork ซึ่งข้อมูลชนิดพื้นฐานทุกชนิดจะ implement เมธอดนี้ เช่น DateTime.Parse(args), Int32.Parse(args) เป็นต้น เมธอด Parse จะคืนค่าเป็นชนิดของข้อมูลที่เราต้องการหากค่า string ที่ส่งเข้ามานั้น มีรูปแบบที่ถูกต้องตามแบบของชนิดข้อมูลที่เราต้องการแปลง และจะโยน exception ออกมาถ้าหากรูปแบบไม่ถูกต้อง เช่น Int32.Parse(“1234”) จะคืนค่าออกมาเป็น 1234 แต่ Int32.Parse(“ABCD”) กรณีนี้จะเกิด exception ครับ ดังนั้นหลักการก็คือ เราดัก exception ด้วยการใส่บล็อก try {} catch{} เข้าไปที่ฟังก์ชั่นที่เราสร้างขึ้นนั่นเอง เมื่อเกิด exception ก็คืนค่าเป็น false กลับมา หากไม่เกิด exception ก็อนุมานว่าค่าที่ส่งเข้าไปนั้นถูกต้อง และคืนค่า true กลับมา มาดูโค้ดกันดีกว่าครับ โค้ดเราสั้นๆ ง่ายๆ ดังต่อไปนี้
IsDate()
public static bool IsDate(object argo) {
try {
DateTime dt = DateTime.Parse(argo.ToString());
if (dt != DateTime.MinValue && dt != DateTime.MaxValue)
return true;
return false;
} catch {
return false;
}
}
public static bool IsDate(object argo) {
try {
DateTime dt = DateTime.Parse(argo.ToString());
if (dt != DateTime.MinValue && dt != DateTime.MaxValue)
return true;
return false;
} catch {
return false;
}
}
IsNumeric()
public static bool IsNumeric(object argo) {
try {
float result = float.Parse(argo.ToString());
return true;
} catch {
return false;
}
}
public static bool IsNumeric(object argo) {
try {
float result = float.Parse(argo.ToString());
return true;
} catch {
return false;
}
}
ฟังก์ชั่นด้านบนทั้งสองฟังก์ชั่น สามารถใช้ได้ใน .Net Framework ตั้งแต่ 1.1 ขึ้นไปเลย เพราะเมธอด Parse นี่มีมาในเวอร์ชั่น 1.1 แล้ว ส่วนผู้ที่ไม่ได้ใช้เฟรมเวอร์กเวอร์ชั่น 1.1 แล้ว และไม่คิดว่าจะกลับไปใช้อีก ก็สามารถใช้ความสามารถที่เพิ่มเติมมาในเฟรมเวอร์กเวอร์ชั่น 2.0 ด้วยการใช้เมธอด TryParse ครับ
เมธอด TryParse นี้เป็นการปรับปรุงให้ดีขึ้นกว่าเมธอด Parse ครับ เพราะมันจะไม่เกิด exception ในกรณีที่แปลงค่าไม่ได้ ซึ่งจะทำให้ประสิทธิภาพโดยรวมของระบบดีขึ้น ทำงานได้เร็วขึ้น เพราะไม่ต้องเสียทรัพยากรของระบบในการจัดการกับ exception เลย เมธอด TryParse นี้จะคืนค่ากลับเป็น Boolean โดยจะมีค่าเป็น false หากแปลงค่าไม่ได้ และเป็น true หากแปลงค่าได้สำเร็จ และในกรณีที่แปลงค่าได้สำเร็จ ค่าที่แปลงได้จะถูกคืนกลับมาในอาร์กิวเม้นต์ตัวที่สอง ที่เราใส่คีย์เวิร์ด out ไว้ข้างหน้านั่นเอง
โค้ดตัวอย่างในการใช้งานทั่วๆไปของเมธอด TryParse
namespace ConsoleApplication1 {
class Program {
static void Main(string[] args) {
DateTime birthDate;
string dateString = "11/05/1987 23:59:59";
if (DateTime.TryParse(dateString, out birthDate)) {
Console.WriteLine("Your birthdate is {0:dd/MM/yyyy hh:mm:ss tt}", birthDate);
} else {
Console.WriteLine("Your birthdate is not specified!!!");
}
Console.ReadKey();
}
}
}
ผลลัพธ์ : Your birthdate is 11/05/1987 11:59:59 PM
namespace ConsoleApplication1 {
class Program {
static void Main(string[] args) {
DateTime birthDate;
string dateString = "11/05/1987 23:59:59";
if (DateTime.TryParse(dateString, out birthDate)) {
Console.WriteLine("Your birthdate is {0:dd/MM/yyyy hh:mm:ss tt}", birthDate);
} else {
Console.WriteLine("Your birthdate is not specified!!!");
}
Console.ReadKey();
}
}
}
ผลลัพธ์ : Your birthdate is 11/05/1987 11:59:59 PM
โค้ดตัวอย่างข้างล่างนี้เป็นการนำเมธอด TryParse มาใช้แทนเมธอด Parse ในฟังก์ชั่น IsDate() และ IsNumeric() ที่เราสร้างขึ้นเองครับ
IsDate()public static bool IsDate(object argo) {
DateTime dt;
if (DateTime.TryParse(argo.ToString(), out dt))
return true;
return false;
}
DateTime dt;
if (DateTime.TryParse(argo.ToString(), out dt))
return true;
return false;
}
IsNumeric()public static bool IsNumeric(object argo) {
float number;
if (float.TryParse(argo.ToString(), out number))
return true;
return false;
}
float number;
if (float.TryParse(argo.ToString(), out number))
return true;
return false;
}
เท่านี้เราก็ได้ฟังก์ชั่นตรวจสอบชนิดของข้อมูลมาใช้โดยไม่ต้องทิ้งความรู้สึกเดิมๆในตอนที่เขียนด้วย VB ไปแล้วครับ
ยังมีอีกวิธีหนึ่งที่ง่ายกว่าเขียนฟังก์ชั่นเลียนแบบการทำงานของ IsDate() และ IsNumeric() เองเสียอีกครับ นั่นคือการเรียกใช้ฟังก์ชั่นเหล่านี้ตรงๆ
ครับ!ไม่ผิดหรอก เราสามารถเรียกใช้ฟังก์ชั่น IsDate(), IsNumeric() และฟังก์ชั่นอื่นๆ ของ VB ได้โดยตรงจาก C# โดย
1. จากโปรเจกต์ของเรา Add Reference ไปยังแอสเซมบลี Microsoft.VisualBasic.dll
2. เพียงเท่านี้เราก็สามารถเข้าถึงเมธอดต่างๆของคลาส Microsoft.VisualBasic.Information ได้แล้วครับ รวมไปถึง IsDate() และ IsNumeric()
1. จากโปรเจกต์ของเรา Add Reference ไปยังแอสเซมบลี Microsoft.VisualBasic.dll
2. เพียงเท่านี้เราก็สามารถเข้าถึงเมธอดต่างๆของคลาส Microsoft.VisualBasic.Information ได้แล้วครับ รวมไปถึง IsDate() และ IsNumeric()
ตัวอย่าง:using Microsoft.VisualBasic;
.
.
.
DateTime? birthDate= (Information.IsDate(args) ? DateTime.Parse(args) : null);
.
.
.
DateTime? birthDate= (Information.IsDate(args) ? DateTime.Parse(args) : null);
โอ้! พระเจ้า! จอร์จ! มันง่ายอะไรอย่างนี้! แต่ว่า . . . ดูก่อน! ท่านผู้เจริญ! ข่าวร้ายครับ จากแหล่งข้อมูลอ้างอิงของเรา วิธีนี้ไม่เป็นที่แนะนำ เพราะว่า คลาสต่างๆในเนมสเปซ Microsoft.VisualBasic (ใน Microsoft.VisualBasic.dll) นั้น เขาทำขึ้นมาเพื่อให้มันเข้ากันได้กับโค้ดภาษา VB รุ่นเก่าๆ (VB4-VB6) เท่านั้นครับ ดังนั้นในอนาคตอันไกล อาจจะไม่มีการสนับสนุนการเข้ากันได้กับโค้ดภาษา VB รุ่นเก่าๆเหล่านั้น (เมื่อมันกลายเป็นภาษารุ่นทวดของทวดของทวด) ก็เป็นได้ เราจึงควรจะใช้ฟังก์ชันใหม่ เมธอดใหม่ที่มีให้ใช้ในเฟรมเวอร์กรุ่นใหม่ๆจะดีกว่า
แหล่งข้อมูลอ้างอิง :
- Parsing Strings, http://msdn.microsoft.com/en-us/library/b4w53z0y(VS.71).aspx, Microsoft MSDN
- TryParse() method in .NET 2.0,http://weblogs.asp.net/hosamkamel/archive/2007/10/02/tryparse-method-in-net-2-0.aspx, Hosam Kamel
- New TryParse Method in .Net 2,http://cs.rthand.com/blogs/blog_with_righthand/archive/2005/11/22/211.aspx, Miha Markic
- IsDate equivalent in C#, http://sivasakki.blogspot.com/2007/08/isdate-equivalent-in-c.html, sivasakki,
- C# Equivalent of VB’s IsNumeric() :C# alternatives to VB’s IsNumeric() function,http://www.codeproject.com/KB/cs/csharp-isnumeric.aspx, Chris Fulstow