ทำไม / เมื่อใดจึงเหมาะสมที่จะแทนที่ ToString


103

ฉันกำลังศึกษา C # และฉันสงสัยว่าประเด็นและประโยชน์ของการลบล้างคืออะไร ToStringอาจเป็นอย่างไรดังที่แสดงในตัวอย่างด้านล่าง

สามารถทำได้ด้วยวิธีที่ง่ายกว่านี้โดยใช้วิธีการทั่วไปโดยไม่ต้องแทนที่?

public string GetToStringItemsHeadings
{
    get { return string.Format("{0,-20} {1, -20}", "Office Email", "Private Email"); }
}


public override string ToString()
{
    string strOut = string.Format("{0,-20} {1, -20}", m_work, m_personal);
    return strOut;
}

4
ขึ้นอยู่กับว่าคุณต้องการใช้เพื่อแสดงวัตถุใน UI ที่ใดจริงๆหรือไม่โดยปกติแล้วจะเป็นเพียงการดีบักเท่านั้นคุณจะเห็นผลลัพธ์ ToString ในหน้าต่างนาฬิกาของ VS (แต่คุณสามารถบรรลุสิ่งนั้นได้ด้วยแอตทริบิวต์ในคลาส) เมื่อคุณมีหัวเรื่องและเอาต์พุตดูเหมือนว่าโปรแกรมนี้ใช้เพื่อถ่ายโอนวัตถุออกโดยใช้Console.WriteLine(obj.GetToStringItemsHeadings); Console.WriteLine(obj);หรือคล้ายกัน
Rup

2
ฉันไม่เข้าใจคำถามจริงๆ ทำได้แตกต่างกันไหม ใช่. แต่ทำไมคุณถึงต้องการทำมันแตกต่างกัน
Konrad Rudolph

5
ฉันจะข้ามGetToStringชื่อคุณสมบัติไปจริงๆ... จากนั้นคุณจะได้รับตัวอย่างเช่นConsole.WriteLine(obj.ItemHeadings)
Svish

และเปลี่ยนคุณสมบัติ ItemHeadings เป็นแบบคงที่เนื่องจากไม่จำเป็นต้องมี "this"
eFloh

คุณอาจต้องการตรวจสอบคำถามนี้: stackoverflow.com/questions/7906828/oo-design-advice-tostring
Yuri Ghensev

คำตอบ:


127
  • ต้องลบล้างToStringไหม ไม่

  • คุณสามารถแสดงสตริงของวัตถุด้วยวิธีอื่นได้หรือไม่? ใช่.

แต่ด้วยการใช้ToStringคุณกำลังใช้วิธีการที่เหมือนกันกับวัตถุทั้งหมดและทำให้คลาสอื่น ๆ รู้เกี่ยวกับวิธีนี้ ตัวอย่างเช่นเมื่อใดก็ตามที่เฟรมเวิร์ก. NET ต้องการแปลงอ็อบเจ็กต์เป็นการแสดงสตริงToStringจะเป็นตัวเลือกหลัก (มีตัวเลือกอื่น ๆ หากคุณต้องการให้ตัวเลือกการจัดรูปแบบละเอียดมากขึ้น)

อย่างเป็นรูปธรรม

Console.WriteLine(yourObject);

yourObject.ToString()จะก่อให้เกิด


13
ใช่. นอกจากนี้ยังมีประโยชน์มากในการพัฒนา MVC หรือ ASP.Net โดยที่@yourObjectและ<%=yourObject%>จะเป็น "ToString-ed"
Ben Lesh

4
นอกจากนี้เมื่อเติมคอมโบบ็อกซ์ ToString เป็นการเรียกเริ่มต้นเพื่อรับข้อความรายการ
Davi Fiamenghi

3
ระวังการปฏิบัติดังกล่าว เรื่องจริง: นักเรียนเอาชนะ ToString ด้วยวิธีการที่นอกเหนือจากการส่งคืนสตริงแล้วให้เปลี่ยนข้อมูล เขากำลังดีบักโปรแกรม แต่ในขณะที่โปรแกรมกำลังยืนอยู่ที่จุดพักค่าก็ยังคงเปลี่ยนแปลง เห็นได้ชัด - ทุกครั้งที่เขาตรวจสอบค่า ToString ถูกเรียกใช้ - ดังนั้นค่าจึงเปลี่ยนไปแม้ว่าโปรแกรมจะไม่ทำงานก็ตาม
JNF

3
@JNF“ การปฏิบัติเช่นนี้” คืออะไร? ToStringไม่ควรเปลี่ยนสถานะของวัตถุจริงๆ แต่นี่ไม่ใช่สิ่งที่ฉันสนับสนุน
Konrad Rudolph

8
@JNF ฉันไม่ยอมรับสิ่งนั้น ToStringเป็นความหมายที่จะถูกแทนที่ ระยะเวลา การระบุข้อแม้ในข้อความนี้ไม่ได้ผล ถ้าคุณทำผิด - ความผิดของคุณเอง อันที่จริงนักเรียนของคุณละเมิดข้อ 4 ในรายการแนวทางอย่างเป็นทางการสำหรับการลบล้างToStringที่โพสต์ไว้ในคำตอบของ David Anderson
Konrad Rudolph

129

ฉันจะให้คำตอบโดยตรงจากFramework Design Guidelinesจาก. NET Development Series

หลีกเลี่ยงข้อยกเว้นในการขว้างปาToString

CONSIDERส่งคืนสตริงเฉพาะที่เกี่ยวข้องกับอินสแตนซ์

พิจารณาว่ามีเอาต์พุตToStringเป็นอินพุตที่ถูกต้องสำหรับวิธีการแยกวิเคราะห์ใด ๆ ในประเภทนี้

ทำให้มั่นใจว่าToStringมีผลข้างเคียงที่สังเกตได้

ทำรายงานข้อมูลที่ละเอียดอ่อนด้านความปลอดภัยผ่านการลบล้างToStringหลังจากเรียกร้องการอนุญาตที่เหมาะสมเท่านั้น หากความต้องการสิทธิ์ล้มเหลวให้ส่งคืนสตริงโดยไม่รวมข้อมูลที่อ่อนไหวด้านความปลอดภัย

Object.ToStringวิธีมีจุดมุ่งหมายที่จะใช้สำหรับการแสดงผลทั่วไปและวัตถุประสงค์ในการแก้จุดบกพร่อง การใช้งานเริ่มต้นเพียงแค่ระบุชื่อประเภทวัตถุ การใช้งานเริ่มต้นไม่มีประโยชน์มากนักและขอแนะนำให้แทนที่เมธอดนี้

ทำแทนที่ToStringเมื่อใดก็ตามที่สามารถส่งคืนสตริงที่มนุษย์อ่านได้ที่น่าสนใจ การใช้งานเริ่มต้นไม่มีประโยชน์มากนักและการใช้งานแบบกำหนดเองมักให้คุณค่ามากกว่า

ทำใช้ชื่อที่จำง่ายมากกว่า ID ที่ไม่ซ้ำกัน แต่อ่านไม่ได้

นอกจากนี้ยังควรค่าแก่การกล่าวถึงเนื่องจาก Chris Sells ยังอธิบายไว้ในหลักเกณฑ์ที่ToStringมักเป็นอันตรายต่อส่วนติดต่อผู้ใช้ โดยทั่วไปกฎทั่วไปของฉันคือการเปิดเผยคุณสมบัติที่จะใช้สำหรับการเชื่อมโยงข้อมูลกับ UI และปล่อยให้การToStringแทนที่เพื่อแสดงข้อมูลการวินิจฉัยแก่ผู้พัฒนา คุณสามารถตกแต่งประเภทของคุณได้DebuggerDisplayAttributeเช่นกัน

DOพยายามที่จะเก็บสตริงกลับมาจากToStringระยะสั้น ดีบักเกอร์ใช้ToStringเพื่อรับการแสดงข้อความของวัตถุที่จะแสดงต่อนักพัฒนา หากสตริงยาวเกินกว่าที่ดีบักเกอร์สามารถแสดงได้ประสบการณ์การดีบักจะถูกขัดขวาง

ทำสตริงการจัดรูปแบบขึ้นอยู่กับวัฒนธรรมเธรดปัจจุบันเมื่อกลับข้อมูลขึ้นอยู่กับวัฒนธรรม

DOให้เกินToString(string format)หรือดำเนินการIFormattableในกรณีที่ผลตอบแทนจากสตริงToStringเป็นวัฒนธรรมที่สำคัญหรือมีวิธีการต่างๆเพื่อจัดรูปแบบสตริง ตัวอย่างเช่นDateTimeให้การโอเวอร์โหลดและการดำเนินการIFormattableให้เกินและการดำเนินการ

อย่าส่งคืนสตริงว่างหรือค่าว่างจากToString

ฉันขอสาบานตามหลักเกณฑ์เหล่านี้และคุณควรทำ ToStringฉันไม่สามารถบอกคุณได้ว่ารหัสของฉันได้ดีขึ้นเพียงแค่นี้หนึ่งแนวทางในการ สิ่งเดียวกันสำหรับสิ่งต่างๆเช่นIEquatable(Of T)IComparable(Of T)และ สิ่งเหล่านี้ทำให้โค้ดของคุณใช้งานได้ดีและคุณจะไม่เสียใจที่สละเวลาเพิ่มเพื่อใช้งานโค้ดใด ๆ

โดยส่วนตัวแล้วฉันไม่เคยใช้อินเทอร์เฟซผู้ใช้ToString มากนักฉันเคยเปิดเผยคุณสมบัติหรือวิธีการจัดเรียงบางอย่าง เวลาส่วนใหญ่ที่คุณควรใช้ToStringเพื่อวัตถุประสงค์ในการดีบักและนักพัฒนาซอฟต์แวร์ ใช้เพื่อแสดงข้อมูลการวินิจฉัยที่สำคัญ


6
คำตอบที่ดีคือแนวทางที่คุณอ้างถึงmsdn.microsoft.com/en-us/library/ms229042.aspxหรือไม่
Jodrell

2
@Jodrell ฉันเชื่อว่านำมาจากFramework Design Guidelines
Jim Schubert

6
จำเป็นต้องมีการอ้างอิงที่ดีกว่า
Ben Voigt

13
ฉันไม่รู้ว่า SO กำลังเปลี่ยนเป็น Wikipedia
David Anderson

14
ไม่ใช่ แต่เมื่อคุณอ้างแนวทางการให้แหล่งที่มาเป็นข้อดีที่ปฏิเสธไม่ได้
Falanwe

39

การลบล้าง ToString()ช่วยให้คุณสามารถแสดงการแสดงสตริงที่มนุษย์อ่านได้ที่เป็นประโยชน์ของคลาส

ซึ่งหมายความว่าผลลัพธ์สามารถเปิดเผยข้อมูลที่เป็นประโยชน์เกี่ยวกับชั้นเรียนของคุณ ตัวอย่างเช่นหากคุณมีคลาส Person คุณอาจเลือกที่จะมีToString()เอาต์พุต ID ของบุคคลชื่อนามสกุลเป็นต้นซึ่งมีประโยชน์อย่างมากเมื่อทำการดีบักหรือบันทึก

เกี่ยวกับตัวอย่างของคุณ - เป็นการยากที่จะบอกได้ว่าการลบล้างของคุณมีประโยชน์หรือไม่โดยที่ไม่รู้ว่าคลาสนี้คืออะไร - แต่การนำไปใช้นั้นใช้ได้


13

เป็นสิ่งที่เหมาะสมเสมอ แต่ควรพิจารณาเจตนาที่อยู่เบื้องหลังสิ่งที่คุณกำลังแสดงอย่างรอบคอบ

คำถามที่ดีกว่าคือการถาม:

ทำไมถึงแทนที่ ToString ()

ToString () คือหน้าต่างเข้าสู่สถานะของวัตถุ เน้นรัฐเป็นข้อกำหนด ภาษา OOP อย่างยิ่งเช่น Java / C # ละเมิดโมเดล OOP โดยการห่อหุ้มทุกอย่างในคลาส ลองนึกภาพคุณกำลังเขียนโค้ดในภาษาที่ไม่เป็นไปตามรูปแบบ OOP ที่ชัดเจน พิจารณาว่าคุณจะใช้คลาสหรือฟังก์ชัน หากคุณจะใช้เป็นฟังก์ชัน (เช่นคำกริยาการกระทำ) และสถานะภายในจะคงไว้เพียงชั่วคราวระหว่างอินพุต / เอาต์พุต ToString () จะไม่เพิ่มค่า

เช่นเดียวกับคนอื่น ๆ ที่กล่าวถึงสิ่งสำคัญคือต้องพิจารณาสิ่งที่คุณส่งออกด้วย ToString () เนื่องจากตัวดีบักเกอร์หรือระบบอื่น ๆ สามารถใช้งานได้

ฉันชอบจินตนาการถึงเมธอด ToString เป็นพารามิเตอร์ --help ของออบเจ็กต์ ควรสั้นอ่านได้ชัดเจนและแสดงง่าย มันควรจะแสดงสิ่งที่วัตถุที่เป็นไม่ได้สิ่งที่มันไม่ ลองพิจารณาดู ...

Use Case - การแยกวิเคราะห์แพ็กเก็ต TCP:

ไม่ใช่การจับภาพเครือข่ายระดับแอปพลิเคชันเท่านั้น แต่มีบางอย่างที่มีเนื้อมากขึ้นเช่นการจับ PCap

คุณต้องการโอเวอร์โหลด ToString () สำหรับเลเยอร์ TCP เพื่อให้คุณสามารถพิมพ์ข้อมูลไปยังคอนโซลได้ มันจะรวมอะไร? คุณอาจคลั่งไคล้และแยกวิเคราะห์รายละเอียด TCP ทั้งหมด (เช่น TCP ซับซ้อน) ...

ซึ่งรวมถึง:

  • พอร์ตต้นทาง
  • พอร์ตปลายทาง
  • ลำดับหมายเลข
  • เลขที่รับทราบ
  • การชดเชยข้อมูล
  • ธง
  • หน้าต่างออฟเซ็ต
  • เช็คซัม
  • ตัวชี้ด่วน
  • ตัวเลือก (ฉันจะไม่ไปที่นั่นด้วยซ้ำ )

แต่คุณต้องการรับขยะทั้งหมดนั้นหรือไม่ถ้าคุณเรียกใช้ TCP ToString () ใน 100 แพ็คเก็ต? ไม่แน่นอนมันจะเกินข้อมูล ทางเลือกที่ง่ายและชัดเจนก็เหมาะสมที่สุด ...

เปิดเผยสิ่งที่ผู้คนคาดหวังว่าจะได้เห็น:

  • พอร์ตต้นทาง
  • พอร์ตปลายทาง

ฉันชอบการส่งออกที่เหมาะสมที่ง่ายสำหรับมนุษย์ที่จะแยก แต่YMMV

TCP:[destination:000, source:000]

ไม่มีอะไรซับซ้อนผลลัพธ์ไม่ได้มีไว้สำหรับให้เครื่องแยกวิเคราะห์ (เช่นเว้นแต่ว่ามีคนใช้รหัสของคุณในทางที่ผิด) จุดประสงค์คือเพื่อให้มนุษย์สามารถอ่านได้

แต่ข้อมูลที่เหลือทั้งหมดที่ฉันพูดถึงก่อนหน้านี้ไม่มีประโยชน์เช่นกัน? ฉันจะไปที่นั่น แต่ก่อนอื่น ...


ToString () หนึ่งในวิธีการที่มีคุณค่าและใช้ไม่ได้ผลตลอดกาล

ด้วยเหตุผลสองประการ:

  1. ผู้คนไม่เข้าใจว่า ToString () มีไว้เพื่ออะไร
  2. คลาส 'Object' พื้นฐานไม่มีเมธอดสตริงอื่นที่สำคัญไม่แพ้กัน

เหตุผลที่ 1 - อย่าละเมิดประโยชน์ของ ToString ():

ผู้คนจำนวนมากใช้ ToString () เพื่อดึงการแสดงสตริงอย่างง่ายของวัตถุ คู่มือ C # ยังระบุ:

ToString เป็นวิธีการจัดรูปแบบหลักใน. NET Framework จะแปลงวัตถุเป็นการแสดงสตริงเพื่อให้เหมาะสำหรับการแสดงผล

แสดง,ไม่ใช่การประมวลผลเพิ่มเติม ไม่ได้หมายความว่าใช้การแสดงสตริงที่ดีของฉันของแพ็คเก็ต TCP ด้านบนและดึงพอร์ตต้นทางโดยใช้ regex :: cringe ::

ขวาวิธีที่จะทำสิ่งที่เป็น ToString โทร () โดยตรงในทรัพย์สิน SourcePort (ซึ่ง BTW เป็น ushort เพื่อ ToString () แล้วควรจะมี)

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

โชคดีที่กลยุทธ์ดังกล่าวเป็นเรื่องธรรมดามาก:

  • ปรับเปลี่ยนได้ (C #)
  • ดอง (Python)
  • JSON (Javascript หรือภาษาใด ๆ ที่ใช้)
  • สบู่
  • ฯลฯ ...

หมายเหตุ: เว้นแต่คุณจะใช้ PHP เพราะ herp-derp มีฟังก์ชันสำหรับสิ่งนั้น :: snicker ::

เหตุผลที่ 2 - ToString () ไม่เพียงพอ:

ฉันยังไม่เห็นภาษาที่ใช้สิ่งนี้เป็นหลัก แต่ฉันได้เห็นและใช้วิธีการนี้ในรูปแบบต่างๆ

บางส่วน ได้แก่ :

  • ToVerboseString ()
  • ToString (verbose = จริง)

โดยพื้นฐานแล้วความยุ่งเหยิงของสถานะของ TCP Packet ควรได้รับการอธิบายเพื่อให้มนุษย์สามารถอ่านได้ เพื่อหลีกเลี่ยงการ 'ตีม้าตาย' เมื่อพูดถึง TCP ฉันจะ 'ชี้นิ้ว' ในกรณี # 1 ที่ฉันคิดว่า ToString () และ ToVerboseString () ไม่ได้ใช้ประโยชน์ ...

ใช้กรณี - อาร์เรย์:

หากคุณใช้ภาษาเดียวเป็นหลักคุณอาจคุ้นเคยกับแนวทางของภาษานั้น สำหรับคนอย่างฉันที่กระโดดไปมาระหว่างภาษาต่างๆจำนวนวิธีที่หลากหลายอาจทำให้รำคาญ

กล่าวคือจำนวนครั้งที่ทำให้ฉันหงุดหงิดนั้นมากกว่าผลรวมของนิ้วทั้งหมดของเทพเจ้าในศาสนาฮินดูทุกองค์รวมกัน

มีต่าง ๆกรณีที่ใช้ภาษาทั่วไปแฮ็กและไม่กี่ที่จะได้รับมันขวา บางคนต้องการการประดิษฐ์ล้อขึ้นมาใหม่บางคนก็ทิ้งน้ำตื้น ๆ บางคนก็ทิ้งแบบลึก ๆ แต่ก็ไม่มีอะไรทำได้อย่างที่ฉันต้องการ ...

สิ่งที่ฉันขอเป็นแนวทางง่ายๆ:

print(array.ToString());

เอาต์พุต: 'Array [x]' หรือ 'Array [x] [y]'

โดยที่ x คือจำนวนรายการในมิติแรกและ y คือจำนวนรายการในมิติที่สองหรือค่าบางค่าที่บ่งชี้ว่ามิติที่ 2 มีรอยหยัก (อาจจะมีช่วงต่ำสุด / สูงสุด?)

และ:

print(array.ToVerboseString());

แสดงผลงานของเธอทั้งหมดในรูปแบบที่สวยงามเพราะฉันชอบสิ่งที่สวยงาม

หวังว่าสิ่งนี้จะช่วยให้เข้าใจหัวข้อที่สร้างความรำคาญให้กับฉันมาเป็นเวลานาน อย่างน้อยที่สุดฉันก็โปรยเหยื่อหมุนรอบตัวเล็กน้อยเพื่อให้ PHPers ลงคะแนนคำตอบนี้


คุณเขียนว่า "ฉันยังไม่เห็นภาษาที่ใช้สิ่งนี้เป็นหลัก" สำหรับฉันแล้วดูเหมือนว่า Python จะเข้ามาใกล้แค่นี้ เช่นการพิมพ์อาร์เรย์ให้ข้อมูลทั้งหมดอย่างรัดกุม นั่นคือสิ่งหนึ่งที่ฉันพลาดใน C # / Java แม้ว่าฉันจะชอบความเข้มงวดของพวกเขา และเมื่อคุณต้องการไปไกลกว่า ToString () มันจะเป็นการดีที่จะมีบางอย่างเช่นไวยากรณ์ความเข้าใจรายการของ Python ฉันเดาว่า string.Join () คล้ายกันแม้ว่าจะมีความยืดหยุ่นน้อยกว่า
Jon Coombs

1
@JCoombs ฉันไม่เห็นด้วยความเข้าใจดีมาก การสำรวจโครงสร้างข้อมูลใน Python ผ่านความเข้าใจทำให้ชีวิตง่ายขึ้นมาก แต่วิธีการนั้นยังคงต้องการความรู้ที่ใกล้ชิดเกี่ยวกับโครงสร้างภายในของวัตถุ สิ่งที่ไม่ชัดเจนเสมอไปกับคลาสที่นำเข้าจากไลบรารีภายนอก เป็นแนวทางปฏิบัติที่ดีสำหรับผู้เขียนไลบรารีในการแทนที่ ToString () และจัดเตรียมการแสดงที่เป็นประโยชน์ที่มนุษย์อ่านได้ แต่ก็เป็นการดีที่จะมีวิธีการถ่ายโอนข้อมูลทั่วไปที่ส่งออกโครงสร้างของวัตถุในรูปแบบที่มนุษย์อ่านได้โดยทั่วไป (เช่น JSON)
Evan Plaice

จุดที่ยอดเยี่ยม ดังนั้นแทนที่จะไม่แสดงอะไรมากไปกว่า typeof โดยทั่วไปมันอาจทำให้เป็นซีเรียลไลซ์อัตโนมัติกับบางอย่างเช่น JSON (จนถึงตอนนี้ฉันเห็นแค่วัตถุ. NET ที่ต่ออนุกรมเป็น XML แต่ฉันยังใหม่กับ. NET) แต่จากนั้นอันตรายอาจเป็นสิ่งล่อใจที่จะถือว่า ToString () เป็นเครื่องอ่านได้หรือไม่? (เช่นคาดว่าจะสามารถ deserialize ได้)
Jon Coombs

1
@JCoombs ใช่ในระดับการทำงาน JSON และ XML ตอบสนองวัตถุประสงค์เดียวกัน หลายคนใช้ ToString เป็นเอาต์พุตที่เครื่องอ่านได้ ไม่ว่าจะเป็นเรื่องเลวร้ายหรือไม่ก็ตาม เนื้อวัวที่ใหญ่ที่สุดของฉัน - บ่อยครั้ง - มันเป็นความเจ็บปวดที่จะแสดงสถานะของวัตถุในรูปแบบที่มนุษย์อ่านได้ การใช้งาน ToString () มักใช้ไม่ได้ผลและการอ่านสถานะของวัตถุนอกรายการเฝ้าดูดีบักเกอร์เป็นความเจ็บปวด การแสดงแบบอนุกรมเป็นสิ่งที่ดีในการสำรองข้อมูลสำหรับการแสดงวัตถุทั้งสถานะ แต่การใช้ ToString ที่ดีกว่าเป็นตัวเลือกที่ดีที่สุด
Evan Plaice

ถ้าToString()มีไว้สำหรับการดีบักเหตุใดจึงเป็นวิธีเดียวที่จะแยกข้อความทั้งหมดจาก StringBuilder ซึ่งเป็นฟังก์ชันที่สำคัญ
Dan W

9

มันเกี่ยวกับการปฏิบัติที่ดีพอ ๆ กับอะไรก็ตามจริงๆ

ToString()ถูกใช้ในหลาย ๆ ที่เพื่อส่งคืนการแสดงสตริงของวัตถุโดยทั่วไปสำหรับการบริโภคโดยมนุษย์ บ่อยครั้งที่สายอักขระเดียวกันนั้นสามารถใช้เพื่อทำให้วัตถุกลับคืนสู่สภาพเดิมได้ (ลองนึกถึงintหรือDateTimeยกตัวอย่างเช่น) แต่นั่นไม่ใช่สิ่งที่กำหนดเสมอไป (ตัวอย่างเช่นต้นไม้อาจมีการแทนค่าสตริงที่มีประโยชน์ซึ่งเพียงแค่แสดงจำนวน แต่คุณไม่สามารถใช้ได้อย่างชัดเจน ที่จะสร้างใหม่)

โดยเฉพาะอย่างยิ่งดีบักเกอร์จะใช้สิ่งนี้เพื่อแสดงตัวแปรในหน้าต่างนาฬิกาหน้าต่างทันที ฯลฯ ดังนั้นจึงToStringมีค่าสำหรับการดีบัก

โดยทั่วไปประเภทดังกล่าวมักจะมีสมาชิกที่ชัดเจนที่ส่งคืนสตริงด้วยเช่นกัน ตัวอย่างเช่นคู่ Lat / Long อาจมีToDecimalDegreesผลตอบแทน"-10, 50"เช่น แต่อาจมีToDegreesMinutesSecondsด้วยเนื่องจากเป็นรูปแบบอื่นสำหรับคู่ Lat / Long ประเภทเดียวกันนั้นอาจแทนที่ToStringด้วยหนึ่งในนั้นเพื่อให้ 'ค่าเริ่มต้น' สำหรับสิ่งต่างๆเช่นการดีบักหรือแม้กระทั่งสำหรับสิ่งต่างๆเช่นการแสดงผลหน้าเว็บ (ตัวอย่างเช่น@โครงสร้างใน Razor เขียนToString()ผลลัพธ์ของนิพจน์ที่ไม่ใช่สตริงไปยัง กระแสเอาต์พุต)


6

object.ToString()แปลงวัตถุเป็นการแสดงสตริง หากคุณต้องการเปลี่ยนสิ่งที่ส่งคืนเมื่อผู้ใช้เรียกToString()ใช้คลาสที่คุณสร้างขึ้นคุณจะต้องแทนที่ToString()ในคลาสนั้น


6

แม้ว่าฉันคิดว่ามีการให้ข้อมูลที่เป็นประโยชน์ที่สุดแล้ว แต่ฉันจะเพิ่มสองเซ็นต์ของฉัน:

  • ToString()หมายถึงการลบล้าง การใช้งานเริ่มต้นจะส่งคืนชื่อประเภทซึ่งในบางครั้งอาจมีประโยชน์ (โดยเฉพาะเมื่อทำงานกับวัตถุจำนวนมาก) แต่ก็ไม่เพียงพอในช่วงเวลาส่วนใหญ่

  • โปรดจำไว้ว่าสำหรับวัตถุประสงค์ในการดีบักคุณสามารถพึ่งพาDebuggerDisplayAttributeได้ คุณสามารถอ่านเพิ่มเติมได้ที่นี่

  • ตามกฎใน POCOs ToString()คุณสามารถแทนที่ POCO เป็นการนำเสนอข้อมูลที่มีโครงสร้างซึ่งโดยปกติจะกลายเป็นสตริง

  • ออกแบบ ToString ให้เป็นตัวแทนข้อความของวัตถุของคุณ อาจจะเป็นฟิลด์และข้อมูลหลักอาจเป็นคำอธิบายว่ามีกี่รายการในคอลเลกชัน ฯลฯ

  • พยายามทำให้สตริงนั้นเป็นบรรทัดเดียวและมีข้อมูลที่จำเป็นเท่านั้น หากคุณมีPersonคลาสที่มีคุณสมบัติ Name, Address, Number เป็นต้นให้ส่งคืนเฉพาะข้อมูลหลัก (ตั้งชื่อหมายเลข ID บางส่วน)

  • ToString()ระวังจะไม่แทนที่การดำเนินงานที่ดีของ ToString()บางคนเรียนกรอบแล้วดำเนินการ การลบล้างการนำไปใช้งานเริ่มต้นนั้นเป็นสิ่งที่ไม่ดี: ผู้คนจะคาดหวังผลลัพธ์บางอย่างToString()และได้รับผลลัพธ์อื่น

อย่ากลัวการใช้งานToString()จริงๆ สิ่งเดียวที่ฉันต้องระวังคือการส่งคืนข้อมูลที่ละเอียดอ่อน นอกเหนือจากนั้นความเสี่ยงยังน้อย แน่นอนว่าอย่างที่บางคนชี้ให้เห็นชั้นเรียนอื่น ๆ จะใช้ ToString ของคุณทุกครั้งที่เข้าถึงข้อมูล แต่เดี๋ยวก่อนการคืนชื่อประเภทเมื่อใดจะถือว่าดีกว่าการได้รับข้อมูลจริง


5

หากคุณไม่ลบล้างToStringคุณจะได้รับการใช้งานคลาสพื้นฐานซึ่งObjectเป็นเพียงชื่อประเภทสั้น ๆ ของคลาส

หากคุณต้องการใช้งานแบบอื่นที่มีความหมายหรือมีประโยชน์มากกว่าToStringนั้นให้ลบล้าง


สิ่งนี้จะมีประโยชน์เมื่อใช้รายการประเภทของคุณเป็นแหล่งข้อมูลสำหรับ a ListBoxตามที่ToStringจะแสดงโดยอัตโนมัติ

สถานการณ์อื่นเกิดขึ้นเมื่อคุณต้องการส่งผ่านประเภทของคุณString.Formatที่เรียกร้องToStringให้รับการแสดงประเภทของคุณ


4

สิ่งที่ยังไม่มีใครพูดถึง: เมื่อลบล้างToString()คุณยังสามารถพิจารณานำไปใช้IFormattableเพื่อให้คุณทำสิ่งต่อไปนี้ได้:

 public override ToString() {
   return string.Format("{0,-20} {1, -20}", m_work, m_personal);
 }

 public ToString(string formatter) {
   string formattedEmail = this.ToString();
   switch (formatter.ToLower()) {
     case "w":
       formattedEmail = m_Work;
       break;
     case "p":
       formattedEmail = m_Personal;
       break;
     case "hw":
       formattedEmail = string.Format("mailto:{0}", m_Work);
       break;
   }
   return formattedEmail;
}

ซึ่งจะมีประโยชน์


คุณช่วยยกตัวอย่างคลาสเฟรมเวิร์กที่มีวิธีการลบล้างได้ไหม สิ่งเดียวที่เกี่ยวข้องที่ฉันทราบในเฟรมเวิร์กคือIFormattibleอินเทอร์เฟซ
tm1

@ tm1 ออบเจ็กต์ใด ๆ ที่สืบทอดมาSystem.ObjectจะมีToString()เมธอดที่เขียนทับได้แต่คุณคิดถูกที่วิธีฟอร์แมตเตอร์ไม่ควรเป็นoverrideและควรอ้างอิงIFormattibleอินเทอร์เฟซเพื่อความสอดคล้องที่สมบูรณ์
Zhaph - Ben Duguid

เกือบ - IFormattableใช้IFormatProviderพารามิเตอร์ ขอบคุณที่แก้ไขโพสต์ของคุณ
tm1

อันที่จริงมันมีสองวิธีค่าที่ฉันแสดงออกอยู่ในรูปที่แสดง)
Zhaph - Ben Duguid

3

ประโยชน์อย่างหนึ่งของการแทนที่ ToString () คือการสนับสนุนเครื่องมือของ Resharper: Alt + Ins -> "การจัดรูปแบบสมาชิก" และจะเขียน ToString () ให้คุณ


2

ในบางกรณีช่วยให้อ่านค่าของคลาสแบบกำหนดเองได้ง่ายขึ้นในหน้าต่างนาฬิกาดีบักเกอร์ ถ้าฉันรู้ว่าฉันต้องการเห็นอะไรในหน้าต่างนาฬิกาเมื่อฉันแทนที่ ToString ด้วยข้อมูลนั้นฉันจะเห็นมัน


1

เมื่อกำหนดโครงสร้าง (User-primitives อย่างมีประสิทธิภาพ) ฉันพบว่าควรมีการจับคู่ToStringและParseและTryParseวิธีการโดยเฉพาะอย่างยิ่งสำหรับการทำให้เป็นอนุกรม XML ในกรณีนี้คุณจะแปลงสถานะทั้งหมดเป็นสตริงเพื่อให้สามารถอ่านได้ในภายหลัง

เรียน แต่มีโครงสร้างสารประกอบอื่น ๆ ที่มักจะซับซ้อนเกินไปสำหรับการใช้และToString วิธีการParseของพวกเขาToStringแทนที่จะบันทึกทั้งรัฐอาจเป็นคำอธิบายง่ายๆที่ช่วยให้คุณระบุสถานะของพวกเขาเช่นตัวระบุที่ไม่ซ้ำกันเช่นชื่อหรือ ID หรืออาจเป็นปริมาณสำหรับรายการ

ยังเป็นร็อบบี้กล่าวว่าเอาชนะToStringช่วยให้คุณสามารถโทรในการอ้างอิงเป็นพื้นฐานเป็นประเภทToStringobject


1

คุณสามารถใช้สิ่งนั้นเมื่อคุณมีวัตถุที่มีความหมายไม่เข้าใจง่ายของการแสดงสตริงเช่นบุคคล ดังนั้นหากคุณต้องการตัวอย่างในการพิมพ์บุคคลนี้คุณสามารถใช้การลบล้างนี้เพื่อเตรียมรูปแบบได้


1

Object.ToStringวิธีการที่ควรจะใช้เพื่อวัตถุประสงค์ในการแก้จุดบกพร่องเท่านั้น การใช้งานดีฟอลต์จะแสดงชื่อประเภทอ็อบเจ็กต์ซึ่งไม่มีประโยชน์มากนัก พิจารณาที่จะลบล้างวิธีนี้เพื่อให้ข้อมูลที่ดีขึ้นสำหรับการวินิจฉัยและการดีบัก โปรดพิจารณาว่าโครงสร้างพื้นฐานการบันทึกมักจะใช้วิธี ToString เช่นกันดังนั้นคุณจะพบส่วนข้อความเหล่านี้ในไฟล์บันทึกของคุณ

อย่าส่งคืนทรัพยากรข้อความที่แปลเป็นภาษาท้องถิ่นภายในObject.ToStringวิธีการ เหตุผลก็คือเมธอด ToString ควรส่งคืนสิ่งที่นักพัฒนาสามารถเข้าใจได้เสมอ นักพัฒนาอาจไม่พูดทุกภาษาที่แอปพลิเคชันรองรับ

ImplementIFormattableอินเตอร์เฟซที่เมื่อคุณต้องการที่จะกลับมาเป็นข้อความที่แปลภาษาที่ใช้งานง่าย อินเทอร์เฟซนี้กำหนด ToString overload ด้วยพารามิเตอร์formatและformatProvider. formatProvider ช่วยให้คุณจัดรูปแบบข้อความด้วยวิธีที่ตระหนักถึงวัฒนธรรม

ดูเพิ่มเติม: Object ToString และ IFormattable


0

ง่ายขึ้นอยู่กับว่าทรัพย์สินของคุณจะถูกนำไปใช้อย่างไร หากคุณต้องการจัดรูปแบบสตริงเพียงครั้งเดียวมันก็ไม่สมเหตุสมผลที่จะเอาชนะมันได้

อย่างไรก็ตามดูเหมือนว่าคุณกำลังลบล้างเมธอด ToString เพื่อไม่ส่งคืนข้อมูลสตริงปกติสำหรับคุณสมบัติของคุณ แต่ใช้รูปแบบการจัดรูปแบบมาตรฐาน เนื่องจากคุณใช้ string.format กับช่องว่างภายใน

เนื่องจากคุณบอกว่าคุณกำลังเรียนรู้แบบฝึกหัดดูเหมือนจะตรงตามหลักการสำคัญในการเขียนโปรแกรมเชิงวัตถุที่เกี่ยวข้องกับการห่อหุ้มและการใช้โค้ดซ้ำ

string.format รับอาร์กิวเมนต์ที่คุณตั้งไว้สำหรับการเติมช่องว่างเพื่อให้แน่ใจว่าคุณสมบัติจะได้รับการจัดรูปแบบเหมือนกันทุกครั้งสำหรับโค้ดใด ๆ ที่เรียกมัน เช่นกันในอนาคตคุณจะต้องเปลี่ยนเพียงที่เดียวแทนที่จะเป็นหลาย ๆ

คำถามที่ดีและคำตอบที่ยอดเยี่ยม!


0

ฉันพบว่ามีประโยชน์ในการแทนที่เมธอด ToString ในคลาสเอนทิตีเนื่องจากช่วยระบุปัญหาในการทดสอบได้อย่างรวดเร็วโดยเฉพาะอย่างยิ่งเมื่อการยืนยันล้มเหลวคอนโซลทดสอบจะเรียกใช้เมธอด ToString บนวัตถุ

แต่ในข้อตกลงกับสิ่งที่ได้กล่าวไปก่อนหน้านี้จะให้การเป็นตัวแทนของวัตถุที่เป็นปัญหาที่มนุษย์สามารถอ่านได้


0

ฉันพอใจกับ Framework Guidelines ที่อ้างถึงในคำตอบอื่น ๆ อย่างไรก็ตามฉันต้องการเน้นวัตถุประสงค์ในการแสดงผลและการดีบัก

ระมัดระวังเกี่ยวกับวิธีที่คุณใช้ToStringในโค้ดของคุณ รหัสของคุณไม่ควรขึ้นอยู่กับการแสดงสตริงของวัตถุ หากเป็นเช่นนั้นคุณควรระบุParseวิธีการที่เกี่ยวข้อง

เนื่องจากToStringสามารถใช้ได้ทุกที่จึงอาจเป็นจุดเจ็บปวดในการบำรุงรักษาได้หากคุณต้องการเปลี่ยนการแสดงสตริงของวัตถุในเวลาต่อมา คุณไม่สามารถตรวจสอบลำดับชั้นการโทรได้ในกรณีนี้เพื่อศึกษาว่าโค้ดบางส่วนจะแตกหรือไม่

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