เหตุใด Convert ToString (null) จึงส่งคืนค่าที่แตกต่างกันหากคุณใช้ null


116
Convert.ToString(null)

ผลตอบแทน

null

ตามที่ฉันคาดไว้.

แต่

Convert.ToString(null as object)

ผลตอบแทน

""

ทำไมถึงแตกต่างกัน?

คำตอบ:


143

มี 2 ​​โอเวอร์โหลดToStringที่เข้ามาเล่นที่นี่

Convert.ToString(object o);
Convert.ToString(string s);

โดยพื้นฐานแล้วคอมไพเลอร์ C # จะพยายามเลือกโอเวอร์โหลดที่เฉพาะเจาะจงที่สุดซึ่งจะทำงานกับอินพุต nullค่าแปลงสภาพให้แก่ชนิดการอ้างอิงใด ๆ ในกรณีนี้stringมีความเฉพาะเจาะจงมากกว่าobjectและด้วยเหตุนี้จึงถูกเลือกเป็นผู้ชนะ

ในnull as objectคุณได้กำหนดประเภทของนิพจน์เป็นobject. ซึ่งหมายความว่ามันไม่สามารถทำงานร่วมกับstringโอเวอร์โหลดได้อีกต่อไปและคอมไพเลอร์จะเลือกobjectโอเวอร์โหลดเนื่องจากเป็นตัวเดียวที่เข้ากันได้

รายละเอียดเกี่ยวกับการทำลายเน็คไทนี้ครอบคลุมในส่วน 7.4.3 ของข้อกำหนดภาษา C #


15
ตกลง. ดังนั้นจึงใช้โอเวอร์โหลดหนึ่งตัวแทนที่จะใช้โอเวอร์โหลด มีเหตุผล. แต่การโอเวอร์โหลดทั้งสองอย่างไม่ควรกลับมาเหมือนเดิมใช่หรือไม่? +1 btw.
John MacIntyre

2
@JohnMacIntyre - ขึ้นอยู่กับทีมพัฒนาไม่ใช่คอมไพเลอร์
JonH

8
@JohnMacIntyre หากคุณดูการใช้งานConvert.ToString(string)มันเป็นเพียงฟังก์ชันระบุตัวตนในขณะที่Convert.ToString(object)ต้องทำตามเส้นทางที่ยากกว่า ในภาพรวมฉันเห็นด้วยว่าพวกเขาควรจะกลับมาเหมือนเดิม แต่ชั้นแปลงสภาพของ BCL ไม่ใช่สิ่งที่ฉันรู้ดีมากและเป็นไปได้ว่ามีเหตุผลที่ดีสำหรับความแตกต่าง (ฉันไม่แน่ใจ)
JaredPar

ฉันมาที่นี่เพื่อค้นหาวิธีการแปลงวัตถุว่างเป็นสตริงว่าง คำตอบสำหรับผู้ค้นหารายอื่นคือ(string)nullหรือถ้าคุณคัดค้านจะเรียกว่า o ดังนั้น(string)o
rayzinnz

65

ต่อจากคำตอบในการแก้ปัญหาโอเวอร์โหลดที่ยอดเยี่ยมของ JaredParคำถามยังคงเป็น "ทำไมConvert.ToString(string)คืนค่าว่าง แต่Convert.ToString(object)กลับstring.Empty"?

และคำตอบก็คือ ... เพราะเอกสารบอกอย่างนั้น :

Convert ToString (สตริง) ส่งคืน "อินสแตนซ์สตริงที่ระบุไม่มีการแปลงจริง"

Convert ToString (object) ส่งคืน "การแสดงสตริงของค่าหรือ String.Empty ถ้าค่าเป็น null"

แก้ไข: ว่านี่เป็น "ข้อบกพร่องในข้อมูลจำเพาะ", "การออกแบบ API ที่ไม่ดี", "เหตุใดจึงระบุเช่นนี้" ฯลฯ - ฉันจะพิจารณาเหตุผลบางประการว่าทำไมฉันไม่เห็น มันเป็นเรื่องใหญ่

  1. System.Convert มีวิธีการแปลงทุกประเภทฐานเป็น ตัวเอง นี่เป็นเรื่องแปลกเนื่องจากไม่จำเป็นต้องมีการแปลงหรือเป็นไปได้ดังนั้นวิธีการจึงจบลงด้วยการส่งคืนพารามิเตอร์ Convert.ToString(string)มีพฤติกรรมเหมือนกัน ฉันคิดว่าสิ่งเหล่านี้อยู่ที่นี่สำหรับสถานการณ์การสร้างโค้ด
  2. Convert.ToString(object)มี 3 nullทางเลือกเมื่อผ่าน โยนคืนค่า null หรือส่งคืนสตริงว่างเปล่า การขว้างปาจะไม่ดี - เป็นทวีคูณด้วยสมมติฐานเหล่านี้ใช้สำหรับรหัสที่สร้างขึ้น การคืนค่า null ต้องการให้ผู้โทรของคุณทำการตรวจสอบค่าว่าง - อีกครั้งไม่ใช่ทางเลือกที่ดีในโค้ดที่สร้างขึ้น กลับสตริงว่างเปล่าดูเหมือนเป็นทางเลือกที่เหมาะสม ส่วนที่เหลือของการSystem.Convertจัดการกับประเภทค่าซึ่งมีค่าเริ่มต้น
  3. เป็นที่ถกเถียงกันว่าการคืนค่า null นั้น "ถูกต้อง" มากกว่าหรือไม่ แต่ string.Empty นั้นใช้งานได้มากกว่า การเปลี่ยนConvert.ToString(string)หมายถึงการทำลายกฎ "ไม่มีการแปลงจริง" เนื่องจากSystem.Convertเป็นคลาสยูทิลิตี้แบบคงที่แต่ละเมธอดสามารถถือว่าเป็นของตัวเองอย่างมีเหตุผล มีสถานการณ์ในโลกแห่งความจริงเพียงไม่กี่สถานการณ์ที่พฤติกรรมนี้ควร "น่าประหลาดใจ" ดังนั้นขอให้การใช้งานเอาชนะความถูกต้อง (เป็นไปได้)

เป็นธรรมหรือไม่ที่จะบอกว่าเป็นข้อบกพร่องในสเป็ค
John MacIntyre

3
นั่นไม่ตอบโจทย์ว่าทำไมถึงเป็นแบบนี้ การพูดว่ามันมีพฤติกรรมเช่นนี้เนื่องจากมีการบันทึกไว้ว่าพฤติกรรมเช่นนี้เป็นเรื่องน่าเบื่อ
CodesInChaos

2
@JohnMacIntyre IMO เป็นเรื่องยุติธรรมที่จะกล่าวได้ว่าเป็นการออกแบบ API ที่แย่มาก
CodesInChaos

7
@CodeInChaos - ไม่ใช่ tautology เว้นแต่คุณจะถือว่าเอกสารนั้นเขียนขึ้นโดยอาศัยพฤติกรรมที่สังเกตได้หลังจากพัฒนา BCL นั่นคงเป็นข้อสันนิษฐานแปลก ๆ ฉันคิดว่า IOW ไม่ใช่ "เอกสารแสดงพฤติกรรมเช่นนี้" แต่เป็น "เอกสารว่าจะมีพฤติกรรมเช่นนี้" - กล่าวคือ " ระบุให้มีพฤติกรรมเช่นนี้"
Mark Brackett

8
เพียง แต่เปลี่ยนคำถามเป็น "เหตุใดจึงระบุให้ประพฤติเช่นนี้"
CodesInChaos
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.