ใน C# การใช้ประเภทค่าเทียบกับประเภทการอ้างอิง

คำถามของฉันคือ:

  • เมื่อใดที่เราควรใช้ประเภทค่าและเมื่อใดเป็นประเภทการอ้างอิง?
  • อะไรคือข้อดีและข้อเสียของสิ่งหนึ่งเหนือสิ่งอื่น?
  • จะเกิดอะไรขึ้นถ้าเราใช้ประเภทการอ้างอิงทุกที่? มีอันตรายอะไรบ้าง?

โปรดหารือถึงข้อดีและข้อเสียของแต่ละข้อด้วย ฉันก็อยากจะเข้าใจเช่นกัน


person Nawaz    schedule 19.01.2011    source แหล่งที่มา
comment
หากคุณตัดสินใจไม่ได้ ก็เกือบจะเป็น class อย่างแน่นอน เป็นเรื่องยากที่จะเขียนโครงสร้าง ถูกต้องตามกฎหมาย ได้ยากอย่างไม่น่าเชื่อ   -  person Marc Gravell    schedule 19.01.2011
comment
สำหรับโปรแกรมเมอร์ชาวตุรกี ฉันมีบล็อกโพสต์เกี่ยวกับเรื่องนี้ sonergonul.net/2012/12/   -  person Soner Gönül    schedule 06.12.2012


คำตอบ (5)


ดูเหมือนว่าจะมีความสับสนมากมายเกี่ยวกับเรื่องนี้ และ Jon Skeet ก็สามารถอธิบายเรื่องนี้ได้ดีในหนังสือของเขา "C# In Depth, 2nd Ed" (ข้อ 2.3)

แนวทางส่วนตัวของฉัน ซึ่งอาจใช่หรือไม่ถูกต้องก็ได้คือใช้เฉพาะโครงสร้าง/การแจงนับ (ประเภทค่า) เพื่อแสดงโครงสร้างข้อมูลอะตอมมิกน้ำหนักเบาที่ฉันรู้ว่าจะใช้บ่อยๆ ในการดำเนินการเชิงตรรกะหรือทางคณิตศาสตร์บางประเภท - ลองคิดดู Point ฯลฯ

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

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

ที่เกี่ยวข้อง: เมื่อใดจึงควรใช้ struct

person Jacobs Data Solutions    schedule 19.01.2011

คุณควรใช้ประเภทค่าสำหรับประเภทขนาดเล็กที่ ไม่เปลี่ยนรูป ซึ่งแสดงถึงค่า
อย่าสร้างโครงสร้างที่ไม่แน่นอน

สำหรับอย่างอื่นทั้งหมด ให้ใช้ประเภทการอ้างอิง

person SLaks    schedule 19.01.2011
comment
โพสต์ของคุณไม่ได้อธิบายว่าทำไมจึงควรใช้ประเภทค่า - person Nawaz; 19.01.2011

ใช้ประเภทค่าสำหรับสิ่งที่ไม่เปลี่ยนรูปซึ่งไม่มีตัวตนเป็นของตัวเอง (1 คือ 1) ใช้ประเภทการอ้างอิงสำหรับสิ่งอื่น

person Oded    schedule 19.01.2011
comment
สตริงควรมีเอกลักษณ์เฉพาะตัวหรือไม่ :) - person Jon Skeet; 19.01.2011
comment
@Jon - กรณีพิเศษ... และใคร ๆ ก็สามารถโต้แย้งได้ว่าควรใช้สตริงเป็นประเภทค่า ชอบที่จะได้ยินสิ่งที่คุณทำ - person Oded; 19.01.2011
comment
@ จอน เมื่อพิจารณาว่ามีพูลสตริงภายใน (เข้าถึงได้ทางอ้อมผ่าน String.IsInterned) ใคร ๆ ก็สามารถโต้แย้งได้ว่าสตริง ทำ มีเอกลักษณ์พิเศษบางอย่าง - person stakx - no longer contributing; 19.01.2011
comment
@Oded และคุณจะจองพื้นที่บนสแต็กเท่าใดสำหรับสตริง ความยาวที่คุณไม่สามารถรู้ได้ - person Marc Gravell; 19.01.2011
comment
@Oded: หากถูกนำมาใช้เป็นประเภทค่า พวกเขาจะต้องมีการอ้างอิงถึงสิ่งอื่นโดยพื้นฐานแล้ว - ท้ายที่สุดแล้วจะไม่ทราบขนาดของสตริงในเวลารวบรวม พวกมันจะเป็นประเภทอ้างอิงที่แกล้งทำเป็นประเภทค่าอย่างมีประสิทธิภาพ ฉันเดาว่าพวกเขา สามารถ มีการนับค่า โดยมีเพียงการอ้างอิงถึงข้อมูลเอง ซึ่งอาจมีประสิทธิภาพในบางสถานการณ์... - person Jon Skeet; 19.01.2011
comment
@Marc Gravell: ไม่ว่าวัตถุบางตัวจะจบลงบนสแต็กหรือบนฮีป (หากมีสิ่งนั้น) ถือเป็นรายละเอียดการใช้งาน บางทีคุณอาจพูดถูก แต่สิ่งนี้ไม่เกี่ยวอะไรกับคำจำกัดความของประเภทค่าและประเภทการอ้างอิงคืออะไร - person stakx - no longer contributing; 19.01.2011
comment
@stakx: ประเด็นก็คือคุณสามารถบอกความแตกต่างระหว่างวัตถุสตริงที่เท่ากันแต่แตกต่างกันสองวัตถุ ใช่แล้ว พวกเขามีตัวตนเป็นของตัวเอง... เราเลือกที่จะเพิกเฉยต่อสิ่งเหล่านั้นเป็นส่วนใหญ่ :) - person Jon Skeet; 19.01.2011
comment
@Oded: โปรดอธิบาย ทำไม เราควรใช้ประเภทค่าเมื่อเขามีตัวเลือกในการใช้ประเภทอ้างอิงเช่นกัน ความแตกต่างคืออะไร? ฉันจะตัดสินใจอย่างไร? - person Nawaz; 19.01.2011
comment
@Oded - ไม่ นี่ไม่ใช่รายละเอียดการใช้งาน: fact; ใน .net ขนาดของโครงสร้างจะต้องเป็นที่รู้จักและคงที่ (ลืมเกี่ยวกับสแต็ก/ฮีป - IL จำเป็นต้องรู้ขนาด); ข้อเท็จจริง: โครงสร้างมีซีแมนทิกส์การคัดลอก (ดังนั้นปัญหาที่มี 50,000 ครั้งเท่ากันเพียงเพราะตัวแปร) สิ่งเหล่านี้มาจากสเป็คอย่างเป็นทางการ - person Marc Gravell; 19.01.2011
comment
@Marc - ฉันแค่หวังที่จะเริ่มการสนทนา ... ดีใจที่เห็นว่าฉันทำ;) - person Oded; 19.01.2011

http://www.albahari.com/valuevsreftypes.aspx

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

person Daniel Casserly    schedule 19.01.2011

ประเภทค่าที่ไม่เปลี่ยนรูปและประเภทการอ้างอิงที่ไม่เปลี่ยนรูปแบบมีความหมายทั้งหมดแต่เหมือนกัน ข้อแตกต่างเพียงอย่างเดียวคือประเภทการอ้างอิงรองรับการตรวจสอบความเท่าเทียมกันของการอ้างอิงที่อาจหรืออาจไม่มีความหมาย และประเภทค่านั้นอาจถูกรวมไว้ใน Nullable(Of T) ในขณะที่ประเภทการอ้างอิงนั้นเป็นโมฆะโดยปริยาย หากประเภทจะไม่เปลี่ยนรูป ขึ้นอยู่กับว่าจะใช้อย่างไร อาจมีเหตุผลด้านประสิทธิภาพที่สนับสนุนโครงสร้างหรือคลาส structs จะเร็วกว่าสำหรับการดำเนินการบางอย่าง (การดำเนินการเกือบทั้งหมด สำหรับขนาดที่น้อยกว่า 4 ไบต์) ในขณะที่คลาสอาจเปลือยเร็วกว่าสำหรับการดำเนินการบางอย่าง (โดยเฉพาะสำหรับสิ่งที่มีขนาดใหญ่กว่า 16 ไบต์) นอกจากนี้ การดำเนินการบางประเภทโดยพื้นฐานแล้วเป็นไปไม่ได้เลยเมื่อมีโครงสร้าง

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

ปัญหาที่แท้จริงเพียงอย่างเดียวของโครงสร้างที่ไม่แน่นอนคือ .net ใช้นามธรรมต่างๆ เพื่อให้ทำงานเป็นส่วนหนึ่งของระบบประเภทรวม และนามธรรมเหล่านี้อาจทำให้สำเนาของโครงสร้างถูกใช้ในสถานที่ที่ควรใช้ต้นฉบับอย่างมีเหตุผล การทดแทนเหล่านี้อาจไม่ชัดเจนเสมอไปเมื่อใด และอาจนำไปสู่พฤติกรรมที่สับสนและผิดพลาดได้

person supercat    schedule 26.01.2011