โครงสร้างเป็นหัวใจสำคัญไม่มีอะไรมากไปกว่าการรวมเขตข้อมูล ใน. NET เป็นไปได้ที่โครงสร้างจะ "แสร้งทำเป็น" เป็นวัตถุและสำหรับโครงสร้างแต่ละประเภท NET จะกำหนดประเภทวัตถุฮีปโดยปริยายด้วยเขตข้อมูลและวิธีการเดียวกันซึ่งการเป็นวัตถุฮีปจะทำงานเหมือนวัตถุ . ตัวแปรที่มีการอ้างอิงถึง heap object (โครงสร้างแบบ "บรรจุกล่อง") จะแสดงความหมายอ้างอิง แต่ตัวแปรที่มีโครงสร้างโดยตรงเป็นเพียงการรวมตัวแปร
ฉันคิดว่าความสับสนของโครงสร้างเทียบกับคลาสส่วนใหญ่เกิดจากการที่โครงสร้างมีสองกรณีการใช้งานที่แตกต่างกันมากซึ่งควรมีแนวทางการออกแบบที่แตกต่างกันมาก แต่หลักเกณฑ์ของ MS ไม่ได้แยกความแตกต่างระหว่างกัน บางครั้งมีความจำเป็นในบางสิ่งบางอย่างที่มีพฤติกรรมเหมือนสิ่งของ ในกรณีนี้แนวทางของ MS ค่อนข้างสมเหตุสมผลแม้ว่า "ขีด จำกัด 16 ไบต์" น่าจะเป็นแบบ 24-32 มากกว่าก็ตาม อย่างไรก็ตามบางครั้งสิ่งที่จำเป็นคือการรวมตัวแปร โครงสร้างที่ใช้เพื่อจุดประสงค์นั้นควรประกอบด้วยฟิลด์สาธารณะจำนวนมากและอาจเป็นไฟล์Equals
ลบล้างการToString
ลบล้างและIEquatable(itsType).Equals
การนำไปใช้งาน โครงสร้างที่ใช้เป็นการรวมเขตข้อมูลไม่ใช่วัตถุและไม่ควรแสร้งทำเป็น จากมุมมองของโครงสร้างความหมายของฟิลด์ไม่ควรมีค่ามากกว่าหรือน้อยไปกว่า "สิ่งสุดท้ายที่เขียนถึงฟิลด์นี้" ความหมายเพิ่มเติมใด ๆ ควรถูกกำหนดโดยรหัสไคลเอ็นต์
ตัวอย่างเช่นถ้า struct ตัวแปรรวมมีสมาชิกMinimum
และMaximum
, struct Minimum <= Maximum
ตัวเองควรจะทำสัญญาว่าจะไม่มี โค้ดที่รับโครงสร้างดังกล่าวเป็นพารามิเตอร์ควรทำงานเหมือนกับว่าถูกส่งผ่านแยกกันMinimum
และมีMaximum
ค่า ข้อกำหนดที่Minimum
ไม่เกินMaximum
ควรถือเป็นข้อกำหนดที่ว่าMinimum
พารามิเตอร์จะต้องไม่มากกว่าการส่งผ่านแยกกันMaximum
หนึ่ง
รูปแบบที่เป็นประโยชน์ในการพิจารณาบางครั้งคือการExposedHolder<T>
กำหนดคลาสไว้ดังนี้:
class ExposedHolder<T>
{
public T Value;
ExposedHolder() { }
ExposedHolder(T val) { Value = T; }
}
หากมีโครงสร้างการรวมตัวแปรอยู่List<ExposedHolder<someStruct>>
ที่ไหนsomeStruct
ก็อาจทำสิ่งต่างๆเช่นmyList[3].Value.someField += 7;
แต่การให้myList[3].Value
รหัสอื่นจะทำให้เนื้อหาของValue
มันแทนที่จะให้วิธีการแก้ไข ในทางตรงกันข้ามหากใช้ก็จะมีความจำเป็นที่จะต้องใช้List<someStruct>
var temp=myList[3]; temp.someField += 7; myList[3] = temp;
ถ้าใครใช้ประเภทคลาสที่เปลี่ยนแปลงได้การเปิดเผยเนื้อหาของmyList[3]
โค้ดภายนอกจะต้องมีการคัดลอกฟิลด์ทั้งหมดไปยังอ็อบเจ็กต์อื่น ถ้าใครใช้ประเภทคลาสที่ไม่เปลี่ยนรูปหรือโครงสร้าง "สไตล์อ็อบเจ็กต์" ก็จำเป็นต้องสร้างอินสแตนซ์ใหม่ที่เหมือนmyList[3]
ยกเว้นsomeField
ที่แตกต่างกันจากนั้นเก็บอินสแตนซ์ใหม่นั้นไว้ในรายการ
หมายเหตุเพิ่มเติมอีกประการหนึ่ง: หากคุณจัดเก็บสิ่งที่คล้ายกันจำนวนมากอาจเป็นการดีที่จะจัดเก็บสิ่งเหล่านี้ไว้ในอาร์เรย์ของโครงสร้างที่อาจซ้อนกันได้โดยควรพยายามรักษาขนาดของแต่ละอาร์เรย์ไว้ระหว่าง 1K ถึง 64K หรือมากกว่านั้น อาร์เรย์ของโครงสร้างมีความพิเศษในการจัดทำดัชนีนั้นจะให้การอ้างอิงโดยตรงไปยังโครงสร้างภายในดังนั้นจึงสามารถพูดว่า "a [12] .x = 5;" แม้ว่าเราจะสามารถกำหนดอ็อบเจกต์ที่คล้ายอาร์เรย์ได้ แต่ C # ไม่อนุญาตให้แชร์ไวยากรณ์ดังกล่าวกับอาร์เรย์