วันนี้จะมาพูดถึงการดึงค่าจาก Dictionary ที่ดูเหมือนจะไม่มีอะไร แต่ไม่ค่อยเห็นการใช้ในแบบที่ควรจะเป็นสักเท่าไหร่ครับ
การใช้ Dictionary ปกติแล้ว มักจะต้องมีการเช็คก่อนว่ามี key อยู่หรือไม่ เนื่องจากการเรียกจาก key ที่ไม่มีอยู่จะทำให้เกิด exception ดังนั้นจึงมักจะเห็น code แบบนี้เป็นปกติ
public string FindX_Naive(Dictionary<string, string> dic)
{
if (dic.ContainsKey("X")) return dic["X"];
else return null;
}
แต่บางท่านก็อาจจะเห็นแล้วว่า ปัญหาของ code นี้คือ มันต้องไปวิ่งหา 2 ครั้ง คือ ที่ dic.ContainsKey("X")
รอบนึง แล้วก็ที่ dic["X"]
อีกรอบนึง แถมยังมี "X"
ในโค้ดสองที่อีกต่างหาก
ซึ่งความจริงแล้ว Dictionary ของ .NET มี method TryGetValue()
ให้ใช้อยู่แล้ว ซึ่งถ้าเปลี่ยนไปใช้แบบนั้น ก็อาจจะเขียนออกมาได้แบบนี้
public string FindX_Try(Dictionary<string, string> dic)
{
string s;
if (dic.TryGetValue("X", out s)) return s;
else return null;
}
คราวนี้ เราก็มี "X"
ที่เดียว และวิ่งหารอบเดียวแล้วคือตอนที่เรียก TryGetValue
แต่ปัญหาคือ code ดูรกรุงรังมาก โดยเฉพาะตัวแปร s ที่ประกาศมาก็ไม่ได้ใช้อะไรมาก แต่โชคดีที่ C# 7 ได้เพิ่มวิธีการประกาศตัวแปร out ให้ทำได้ตรงที่เรียกใช้เลย ดังนั้นเราก็จะสามารถเขียนให้กระชับกว่าเดิมได้
public string FindX_Try_OutVar(Dictionary<string, string> dic)
{
if (dic.TryGetValue("X", out var s)) return s;
else return null;
}
แต่เขียนให้สั้นกว่านี้ก็ยังได้ โดยใช้ conditional operator และ expresion bodied method
public string FindX_Final(Dictionary<string, string> dic)
=> dic.TryGetValue("X", out var s) ? s : null;
ซึ่งจะเห็นว่าเขียนสั้นพอ ๆ กับแบบแรก แต่ถูกต้องในแบบที่ควรจะใช้มากกว่า
สรุปคือ ถึงแม้ว่าการเขียนแบบตัวอย่างแรกสุดจะดูเข้าใจง่าย แต่ก็เป็นการสิ้นเปลืองในการที่จะต้องวิ่งหาใน Dictionary สองรอบ ซึ่งก่อนหน้านี้ก็พอมีข้ออ้างได้ว่า code ดูง่ายกว่าเพราะการเขียนแบบใช้ out ก็จะดูเยิ่นเย้อ แต่ตั้งแต่ C# 7 เป็นต้นมา ก็มี feature พอที่จะเขียนรูปแบบดังกล่าวให้อ่านง่ายและได้ประสิทธิภาพดีกว่าแล้วครับ
Top comments (0)