เมื่อใดที่ฉันควรใช้ struct แทนคลาส


302

MSDN บอกว่าคุณควรใช้ structs เมื่อคุณต้องการวัตถุที่มีน้ำหนักเบา มีสถานการณ์อื่น ๆ อีกหรือไม่เมื่อมีโครงสร้างที่ต้องการมากกว่าคลาส?

บางคนอาจลืมว่า:

  1. structsสามารถมีวิธีการ
  2. structsไม่สามารถสืบทอด

ฉันเข้าใจความแตกต่างทางเทคนิคระหว่าง structs และคลาสฉันแค่รู้สึกไม่ดีเมื่อจะใช้ struct


เตือนความทรงจำ - สิ่งที่คนส่วนใหญ่มักจะลืมในบริบทนี้คือใน C # structs สามารถมีวิธีได้เช่นกัน
petr k.

คำตอบ:


295

MSDN มีคำตอบ: การเลือกระหว่างการเรียนและโครงสร้าง

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

อย่ากำหนดโครงสร้างเว้นแต่ประเภทจะมีคุณสมบัติดังต่อไปนี้ทั้งหมด:

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

1
บางทีฉันอาจขาดอะไรบางอย่างที่เห็นได้ชัด แต่ฉันก็ไม่ได้รับเหตุผลที่อยู่เบื้องหลังส่วน "ไม่เปลี่ยนรูป" ทำไมถึงจำเป็น? มีคนอธิบายได้ไหม
Tamas Czinege

3
พวกเขาอาจแนะนำสิ่งนี้เพราะถ้าโครงสร้างนั้นไม่เปลี่ยนรูปแล้วมันจะไม่สำคัญว่ามันจะมีค่าความหมายมากกว่าความหมายอ้างอิง ความแตกต่างนั้นสำคัญก็ต่อเมื่อคุณทำการเปลี่ยนแปลงวัตถุ / โครงสร้างหลังจากทำการคัดลอก
สตีเฟ่นซี. เหล็ก

@DrJokepu: ในบางสถานการณ์ระบบจะทำสำเนาชั่วคราวของโครงสร้างและอนุญาตให้คัดลอกนั้นจะถูกส่งผ่านโดยอ้างอิงถึงรหัสที่เปลี่ยนแปลงมัน; เนื่องจากสำเนาชั่วคราวจะถูกโยนทิ้งการเปลี่ยนแปลงจะหายไป ปัญหานี้จะรุนแรงโดยเฉพาะอย่างยิ่งถ้า struct มีวิธีการที่กลายพันธุ์ ฉันไม่เห็นด้วยอย่างชัดเจนกับความคิดที่ว่าความไม่แน่นอนเป็นเหตุผลที่ทำให้บางสิ่งบางอย่างในชั้นเรียนตั้งแต่ - แม้ว่าข้อบกพร่องบางอย่างใน c # และ vb.net, struct ที่ไม่แน่นอนให้ความหมายที่เป็นประโยชน์ที่ไม่สามารถทำได้ด้วยวิธีอื่น ไม่มีเหตุผลทางความหมายที่ชอบโครงสร้างที่ไม่เปลี่ยนรูปแบบของคลาส
supercat

4
@Chuu: ในการออกแบบคอมไพเลอร์ JIT นั้น Microsoft ตัดสินใจที่จะปรับโค้ดให้เหมาะสมสำหรับการคัดลอก struct ที่มีขนาด 16 ไบต์หรือเล็กกว่า นี่หมายความว่าการคัดลอกโครงสร้างแบบ 17 ไบต์อาจช้ากว่าการคัดลอกโครงสร้างแบบ 16 ไบต์อย่างมีนัยสำคัญ ฉันไม่เห็นเหตุผลใดที่จะคาดหวังให้ Microsoft ขยายการเพิ่มประสิทธิภาพดังกล่าวไปยังโครงสร้างที่มีขนาดใหญ่ขึ้น แต่สิ่งสำคัญที่ควรทราบคือในขณะที่โครงสร้าง 17 ไบต์อาจช้ากว่าการคัดลอกกว่าโครงสร้าง 16 ไบต์มีหลายกรณีที่โครงสร้างขนาดใหญ่อาจมีประสิทธิภาพมากกว่า วัตถุคลาสขนาดใหญ่และความได้เปรียบเชิงโครงสร้างของ structs ขึ้นกับขนาดของโครงสร้าง
supercat

3
@Chuu: การใช้รูปแบบการใช้งานเดียวกันกับโครงสร้างที่มีขนาดใหญ่ตามที่ต้องการกับคลาสนั้นจะส่งผลให้เกิดโค้ดที่ไม่มีประสิทธิภาพ แต่วิธีการแก้ปัญหาที่เหมาะสมมักจะไม่ใช่การแทนที่ structs ด้วยคลาส แต่แทนที่จะใช้ struct อย่างมีประสิทธิภาพมากกว่า สิ่งที่สะดุดตาที่สุดคือควรหลีกเลี่ยงการส่งผ่านหรือคืนค่าโครงสร้างตามค่า ส่งต่อเป็นrefพารามิเตอร์เมื่อใดก็ตามที่สมเหตุสมผล ผ่านโครงสร้างที่มี 4,000 เขตข้อมูลเป็นพารามิเตอร์การอ้างอิงไปยังวิธีการที่เปลี่ยนแปลงอย่างใดอย่างหนึ่งจะถูกกว่าการส่งผ่านโครงสร้างที่มี 4 เขตข้อมูลตามมูลค่าให้กับวิธีการที่ส่งกลับรุ่นที่แก้ไข
supercat

53

ฉันประหลาดใจที่ฉันไม่ได้อ่านคำตอบก่อนหน้านี้ซึ่งฉันพิจารณาเรื่องที่สำคัญที่สุด:

ฉันใช้ structs เมื่อฉันต้องการประเภทที่ไม่มีตัวตน ตัวอย่างเช่นจุด 3D:

public struct ThreeDimensionalPoint
{
    public readonly int X, Y, Z;
    public ThreeDimensionalPoint(int x, int y, int z)
    {
        this.X = x;
        this.Y = y;
        this.Z = z;
    }

    public override string ToString()
    {
        return "(X=" + this.X + ", Y=" + this.Y + ", Z=" + this.Z + ")";
    }

    public override int GetHashCode()
    {
        return (this.X + 2) ^ (this.Y + 2) ^ (this.Z + 2);
    }

    public override bool Equals(object obj)
    {
        if (!(obj is ThreeDimensionalPoint))
            return false;
        ThreeDimensionalPoint other = (ThreeDimensionalPoint)obj;
        return this == other;
    }

    public static bool operator ==(ThreeDimensionalPoint p1, ThreeDimensionalPoint p2)
    {
        return p1.X == p2.X && p1.Y == p2.Y && p1.Z == p2.Z;
    }

    public static bool operator !=(ThreeDimensionalPoint p1, ThreeDimensionalPoint p2)
    {
        return !(p1 == p2);
    }
}

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


4
ปิดบิตของหัวข้อ แต่ทำไมคุณต้องโยน ArgumentException เมื่อ obj ไม่ใช่ ThreeDimensionalPoint คุณไม่ควรกลับเท็จในกรณีนั้นหรือ
Svish

4
ถูกต้องฉันกระตือรือร้นมากเกินไป return falseเป็นสิ่งที่ควรได้รับการแก้ไข
Andrei Rînea

เหตุผลที่น่าสนใจในการใช้งาน struct ฉันได้สร้างคลาสด้วย GetHashCode และ Equals ที่กำหนดไว้คล้ายกับสิ่งที่คุณแสดงที่นี่ แต่จากนั้นฉันก็ต้องระวังไม่ให้กลายพันธุ์อินสแตนซ์เหล่านั้นถ้าฉันใช้มันเป็นกุญแจพจนานุกรม อาจจะปลอดภัยกว่านี้หากฉันกำหนดไว้เป็น structs (เพราะกุญแจจะเป็นสำเนาของฟิลด์ในขณะที่โครงสร้างกลายเป็นคีย์พจนานุกรมดังนั้นคีย์จะยังคงไม่เปลี่ยนแปลงถ้าฉันเปลี่ยนต้นฉบับในภายหลัง)
ToolmakerSteve

ในตัวอย่างของคุณก็โอเคเพราะคุณมี 12 ไบต์เท่านั้น แต่โปรดจำไว้ว่าถ้าคุณมีฟิลด์จำนวนมากในโครงสร้างนั้นที่เกิน 16 ไบต์คุณต้องพิจารณาใช้คลาสและแทนที่เมธอด GetHashCode และ Equals
Daniel Botero Correa

ประเภทค่าใน DDD ไม่ได้หมายความว่าคุณควรใช้ประเภทค่าใน C #
Darragh

26

Bill Wagner มีบทเกี่ยวกับเรื่องนี้ในหนังสือของเขา "Effective c #" ( http://www.amazon.com/Effective-Specific-Ways-Improve-Your/dp/0321245660 ) เขาสรุปโดยใช้หลักการต่อไปนี้:

  1. ความรับผิดชอบหลักของการจัดเก็บข้อมูลประเภทคืออะไร?
  2. ส่วนต่อประสานสาธารณะถูกกำหนดโดยคุณสมบัติที่เข้าถึงหรือแก้ไขข้อมูลสมาชิกได้หรือไม่?
  3. คุณแน่ใจหรือไม่ว่าประเภทของคุณจะไม่มีคลาสย่อย?
  4. คุณแน่ใจหรือว่าประเภทของคุณจะไม่ได้รับการปฏิบัติ polymorphically?

หากคุณตอบ 'ใช่' สำหรับคำถามทั้ง 4 ข้อให้ใช้ struct มิฉะนั้นให้ใช้คลาส


1
ดังนั้น ... วัตถุการถ่ายโอนข้อมูล (DTO) ควรเป็น struct หรือไม่
แล่นเรือ

1
ฉันว่าใช่ถ้าเป็นไปตามเกณฑ์ 4 ข้อที่อธิบายไว้ข้างต้น ทำไมวัตถุการถ่ายโอนข้อมูลจะต้องได้รับการปฏิบัติในวิธีเฉพาะ?
Bart Gijssens

2
@cruizer ขึ้นอยู่กับสถานการณ์ของคุณ ในโครงการหนึ่งเรามีเขตตรวจสอบทั่วไปใน DTO ของเราและด้วยเหตุนี้จึงเขียนฐาน DTO ที่คนอื่นสืบทอดมา
Andrew Grothe

1
ทั้งหมด (2) ดูเหมือนหลักการที่ยอดเยี่ยม จะต้องเห็นเหตุผลของเขาที่จะรู้ว่าสิ่งที่เขาหมายถึงโดย (2) และทำไม
ToolmakerSteve

1
@ToolmakerSteve: คุณจะต้องอ่านหนังสือเล่มนั้น อย่าคิดว่ามันยุติธรรมที่จะคัดลอก / วางส่วนใหญ่ของหนังสือ
Bart Gijssens


12

ฉันจะใช้ structs เมื่อ:

  1. วัตถุควรอ่านได้อย่างเดียว (ทุกครั้งที่คุณผ่าน / กำหนดโครงสร้างที่ได้รับการคัดลอก) วัตถุที่อ่านอย่างเดียวนั้นยอดเยี่ยมเมื่อพูดถึงการประมวลผลแบบมัลติเธรดเนื่องจากไม่จำเป็นต้องล็อคในกรณีส่วนใหญ่

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


10

ใช้คลาสหาก:

  • ตัวตนของมันเป็นสิ่งสำคัญ โครงสร้างได้รับการคัดลอกโดยปริยายเมื่อถูกส่งผ่านโดยค่าลงในวิธีการ
  • มันจะมีหน่วยความจำขนาดใหญ่
  • มันต้องการเขตข้อมูล initializers
  • คุณต้องสืบทอดจากคลาสฐาน
  • คุณต้องการพฤติกรรมที่หลากหลาย

ใช้โครงสร้างถ้า:

  • มันจะทำหน้าที่เหมือนรูปแบบดั้งเดิม (int, long, byte, ฯลฯ )
  • ต้องมีหน่วยความจำขนาดเล็ก
  • คุณกำลังเรียกใช้เมธอด P / Invoke ที่ต้องการโครงสร้างที่จะส่งผ่านโดยค่า
  • คุณต้องลดผลกระทบของการรวบรวมขยะต่อประสิทธิภาพของแอปพลิเคชัน
  • เขตข้อมูลของมันจะต้องเริ่มต้นได้เฉพาะกับค่าเริ่มต้นของพวกเขา ค่านี้จะเป็นศูนย์สำหรับประเภทตัวเลขเท็จสำหรับประเภทบูลีนและเป็นโมฆะสำหรับประเภทอ้างอิง
    • โปรดทราบว่าใน C # 6.0 structs สามารถมีตัวสร้างเริ่มต้นที่สามารถใช้ในการเริ่มต้นเขตข้อมูลของ struct เป็นค่าที่ไม่ใช่ค่าเริ่มต้น
  • คุณไม่จำเป็นต้องสืบทอดจากคลาสพื้นฐาน (นอกเหนือจาก ValueType ซึ่งรับโครงสร้างทั้งหมด)
  • คุณไม่ต้องการพฤติกรรม polymorphic

5

ฉันมักจะใช้ struct เมื่อฉันต้องการจัดกลุ่มค่าสองสามค่าเพื่อส่งสิ่งต่าง ๆ กลับมาจากการเรียกใช้เมธอด แต่ฉันไม่จำเป็นต้องใช้มันสำหรับทุกสิ่งหลังจากฉันอ่านค่าเหล่านั้นแล้ว เป็นเพียงวิธีในการรักษาสิ่งที่สะอาด ฉันมักจะมองสิ่งต่าง ๆ ใน struct ว่า "throwaway" และสิ่งต่าง ๆ ในชั้นเรียนมีประโยชน์มากกว่าและ "ใช้งานได้"


4

หากเอนทิตีจะไม่เปลี่ยนรูปคำถามของการใช้ struct หรือคลาสจะเป็นหนึ่งในการทำงานมากกว่าซีแมนทิกส์ บนระบบ 32/64 บิตการอ้างอิงคลาสต้องการ 4/8 ไบต์เพื่อจัดเก็บโดยไม่คำนึงถึงจำนวนข้อมูลในคลาส การคัดลอกการอ้างอิงระดับจะต้องคัดลอก 4/8 ไบต์ ในทางตรงกันข้ามทุกอย่างชัดเจนอินสแตนซ์ของคลาสจะมีค่าใช้จ่าย 8/16 ไบต์นอกเหนือจากข้อมูลที่เก็บไว้และค่าใช้จ่ายหน่วยความจำของการอ้างอิง สมมติว่าหนึ่งต้องการอาร์เรย์ของเอนทิตี 500 แต่ละอันมีจำนวนเต็ม 32 บิตสี่ตัว หากเอนทิตีเป็นประเภทโครงสร้างอาร์เรย์จะต้องการ 8,000 ไบต์โดยไม่คำนึงว่าหน่วยงานทั้งหมด 500 รายการนั้นเหมือนกันทั้งหมดแตกต่างกันหรืออยู่ระหว่าง หากเอนทิตีเป็นประเภทคลาสอาร์เรย์ของการอ้างอิง 500 รายการจะใช้เวลา 4,000 ไบต์ หากการอ้างอิงทั้งหมดชี้ไปที่วัตถุที่แตกต่างกันวัตถุจะต้องเพิ่ม 24 ไบต์ต่อแต่ละ (12,000 ไบต์สำหรับทั้งหมด 500) รวมเป็น 16,000 ไบต์ - สองเท่าของค่าใช้จ่ายในการจัดเก็บประเภท struct ในทางกลับกันของโค้ดที่สร้างอินสแตนซ์ของวัตถุหนึ่งอินสแตนซ์แล้วคัดลอกการอ้างอิงไปยังสล็อตอาเรย์ทั้งหมด 500 รายการค่าใช้จ่ายทั้งหมดจะเป็น 24 ไบต์สำหรับอินสแตนซ์นั้นและ 4 000 สำหรับอาร์เรย์ - รวม 4,024 ไบต์ การออมที่สำคัญ สถานการณ์ไม่กี่อย่างจะได้ผลเช่นเดียวกับสถานการณ์สุดท้าย แต่ในบางกรณีอาจเป็นไปได้ที่จะคัดลอกการอ้างอิงบางอย่างไปยังสล็อตอาเรย์พอที่จะทำให้การแบ่งปันดังกล่าวคุ้มค่า

ถ้าเอนทิตีควรจะไม่แน่นอนคำถามว่าจะใช้คลาสหรือ struct นั้นง่ายกว่ากัน สมมติว่า "Thing" เป็นโครงสร้างหรือคลาสที่มีเขตข้อมูลจำนวนเต็มชื่อ x และมีรหัสต่อไปนี้

  สิ่งที่ t1, t2;
  ...
  t2 = t1;
  t2.x = 5;

มีใครต้องการให้คำสั่งหลังจะส่งผลกระทบต่อ t1.x?

ถ้าสิ่งนั้นเป็นประเภทคลาส t1 และ t2 จะเท่ากันหมายถึง t1.x และ t2.x ก็จะเทียบเท่ากัน ดังนั้นคำสั่งที่สองจะมีผลต่อ t1.x หากสิ่งนั้นเป็นประเภทโครงสร้าง t1 และ t2 จะเป็นอินสแตนซ์ที่แตกต่างกันหมายถึง t1.x และ t2.x จะอ้างถึงจำนวนเต็มที่แตกต่างกัน ดังนั้นคำสั่งที่สองจะไม่ส่งผลกระทบต่อ t1.x

โครงสร้างที่ไม่แน่นอนและคลาสที่ไม่แน่นอนมีพฤติกรรมที่แตกต่างกันโดยพื้นฐานแม้ว่า. net จะมีข้อผิดพลาดบางอย่างในการจัดการการกลายพันธุ์ของ struct หากต้องการพฤติกรรมประเภทค่า (หมายความว่า "t2 = t1" จะคัดลอกข้อมูลจาก t1 ถึง t2 ในขณะที่ปล่อยให้ t1 และ t2 เป็นอินสแตนซ์ที่แตกต่างกัน) และถ้าใครสามารถมีชีวิตอยู่กับ quirks ในการจัดการประเภทค่า โครงสร้าง ถ้าใครต้องการซีแมนทิกส์ประเภทค่า แต่สิ่งที่แปลกประหลาดของ. เน็ตจะทำให้เกิดความหมายเชิงเซกชั่นประเภทค่าในแอปพลิเคชันของคนใช้คลาสและพึมพำ


3

นอกจากนี้คำตอบที่ยอดเยี่ยมข้างต้น:

โครงสร้างเป็นประเภทค่า

พวกเขาไม่เคยสามารถกำหนดให้ไม่มีอะไร

การตั้งค่าโครงสร้าง = ไม่มีอะไรจะตั้งค่าประเภททั้งหมดเป็นค่าเริ่มต้น


2

เมื่อคุณไม่ต้องการพฤติกรรมจริงๆ แต่คุณต้องการโครงสร้างมากกว่าอาร์เรย์หรือพจนานุกรมอย่างง่าย

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


ทำไมคุณพูดแบบนั้น? โครงสร้างสามารถมีวิธีการ
Esteban Araya

2

ในฐานะที่เป็น @Simon กล่าวว่า structs ให้ความหมาย "ประเภทค่า" ดังนั้นหากคุณต้องการพฤติกรรมที่คล้ายกันกับชนิดข้อมูลในตัวให้ใช้ struct เนื่องจาก structs ถูกส่งผ่านโดยการคัดลอกคุณต้องการให้แน่ใจว่ามันมีขนาดเล็กประมาณ 16 ไบต์


2

มันเป็นหัวข้อเก่า แต่ต้องการให้การทดสอบเกณฑ์มาตรฐานอย่างง่าย

ฉันได้สร้างไฟล์. cs สองไฟล์:

public class TestClass
{
    public long ID { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
}

และ

public struct TestStruct
{
    public long ID { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
}

เรียกใช้เกณฑ์มาตรฐาน:

  • สร้าง 1 TestClass
  • สร้าง 1 TestStruct
  • สร้าง 100 TestClass
  • สร้าง 100 TestStruct
  • สร้าง 10,000 TestClass
  • สร้าง 10,000 TestStruct

ผล:

BenchmarkDotNet=v0.12.0, OS=Windows 10.0.18362
Intel Core i5-8250U CPU 1.60GHz (Kaby Lake R), 1 CPU, 8 logical and 4 physical cores
.NET Core SDK=3.1.101
[Host]     : .NET Core 3.1.1 (CoreCLR 4.700.19.60701, CoreFX 4.700.19.60801), X64 RyuJIT  [AttachedDebugger]
DefaultJob : .NET Core 3.1.1 (CoreCLR 4.700.19.60701, CoreFX 4.700.19.60801), X64 RyuJIT


|         Method |           Mean |         Error |        StdDev |     Ratio | RatioSD | Rank |    Gen 0 | Gen 1 | Gen 2 | Allocated |
|--------------- |---------------:|--------------:|--------------:|----------:|--------:|-----:|---------:|------:|------:|----------:|

|      UseStruct |      0.0000 ns |     0.0000 ns |     0.0000 ns |     0.000 |    0.00 |    1 |        - |     - |     - |         - |
|       UseClass |      8.1425 ns |     0.1873 ns |     0.1839 ns |     1.000 |    0.00 |    2 |   0.0127 |     - |     - |      40 B |
|   Use100Struct |     36.9359 ns |     0.4026 ns |     0.3569 ns |     4.548 |    0.12 |    3 |        - |     - |     - |         - |
|    Use100Class |    759.3495 ns |    14.8029 ns |    17.0471 ns |    93.144 |    3.24 |    4 |   1.2751 |     - |     - |    4000 B |
| Use10000Struct |  3,002.1976 ns |    25.4853 ns |    22.5920 ns |   369.664 |    8.91 |    5 |        - |     - |     - |         - |
|  Use10000Class | 76,529.2751 ns | 1,570.9425 ns | 2,667.5795 ns | 9,440.182 |  346.76 |    6 | 127.4414 |     - |     - |  400000 B |

1

อืม ...

ฉันจะไม่ใช้การรวบรวมขยะเป็นข้อโต้แย้งสำหรับ / กับการใช้งาน structs กับคลาส heap ที่มีการจัดการทำงานคล้ายกับสแต็ก - การสร้างวัตถุเพียงวางไว้ที่ด้านบนของฮีปซึ่งเกือบจะเร็วเท่ากับการจัดสรรบนสแต็ก นอกจากนี้หากวัตถุมีอายุสั้นและไม่สามารถอยู่รอดได้ในรอบ GC การยกเลิกการจัดสรรจะไม่มีค่าใช้จ่ายเนื่องจาก GC จะทำงานกับหน่วยความจำที่ยังคงเข้าถึงได้เท่านั้น (ค้นหา MSDN มีบทความหลายเรื่องเกี่ยวกับการจัดการหน่วยความจำ. NET ฉันแค่ขี้เกียจเกินไปที่จะขุดหาพวกเขา)

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

อย่างไรก็ตามจุดสี่จุดในบทความ MSDN ที่โพสต์ข้างต้นนั้นเป็นแนวทางที่ดี


1
ถ้าบางครั้งคุณต้องการซีแมนทิกส์อ้างอิงด้วย struct ให้ประกาศclass MutableHolder<T> { public T Value; MutableHolder(T value) {Value = value;} }และจากนั้น a MutableHolder<T>จะเป็นอ็อบเจกต์ที่มีคลาสซีแมนทิกส์ที่เปลี่ยนแปลงไม่Tได้
supercat

1

Structs อยู่ใน Stack ไม่ใช่ Heap ดังนั้นจึงเป็น thread safe และควรใช้เมื่อใช้รูปแบบการถ่ายโอนวัตถุคุณไม่ต้องการใช้วัตถุบน Heap ที่ระเหยง่ายคุณต้องการในกรณีนี้เพื่อใช้ Call Stack นี่เป็นกรณีพื้นฐานสำหรับการใช้ struct ฉันรู้สึกประหลาดใจกับคำตอบที่นี่


-3

ฉันคิดว่าคำตอบที่ดีที่สุดคือการใช้ struct เมื่อสิ่งที่คุณต้องการคือชุดของคุณสมบัติคลาสเมื่อเป็นชุดของคุณสมบัติและพฤติกรรม


structs สามารถมีวิธีการเกินไป
Nithin Chandran

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