เหตุใดจึงมีข้อ จำกัด () ใหม่ใน C # แต่ไม่มีข้อ จำกัด อื่นที่คล้ายคลึงกัน


19

ใน C # generics เราสามารถประกาศข้อ จำกัด สำหรับพารามิเตอร์ชนิดจะมีคอนสตรัคเริ่มต้นด้วยการพูดว่าT where T : new()อย่างไรก็ตามไม่มีข้อ จำกัด อื่น ๆ เช่นนี้ที่ถูกต้อง - new(string)ตัวอย่างเช่น ฯลฯ

จากมุมมองของการออกแบบภาษาและ / หรือการนำไปใช้งานอะไรคือสาเหตุของสิ่งนี้?

มีบางอย่างในการทำงานของคอนสตรัคเตอร์หรือวิธีการใช้งานระบบพิมพ์ที่ห้ามสิ่งนี้ (หรืออย่างน้อยก็ทำให้ยากขึ้น)? ถ้าเป็นเช่นนั้นมันคืออะไร? ผมจำได้อ่านบางที่default(T)จริงคอมไพล์สำหรับnew T() T : structมันเกี่ยวข้องกับสิ่งนี้หรือเปล่า?

หรือเป็นเพียงการตัดสินใจออกแบบเพื่อหลีกเลี่ยงการทำให้ภาษาซับซ้อนเกินไป?


new(string)ไม่ใช่ข้อ จำกัด ของตัวสร้างเริ่มต้น คำถามของคุณมีค่าเท่ากับการพูดว่า "ทำไมจึงไม่มีข้อ จำกัด ที่ต้องมีลายเซ็นคอนสตรัคเตอร์เฉพาะ" มีโอกาสมากเพราะข้อ จำกัด ดังกล่าวจะไม่มีประโยชน์อย่างยิ่ง
Robert Harvey

3
@ RobertHarvey ใช่มันเป็นสิ่งที่ฉันพูด ฉันกำลังถามว่าเป็นสิ่งที่ทำให้ตัวสร้างเริ่มต้นการใช้งานพิเศษที่ชาญฉลาดหรือถ้ามันเป็นเพียงตัวเลือกโดยพลการที่จะรวมสิ่งนี้และไม่อื่น ๆ
Theodoros Chatzigiannakis

ตัวสร้างเริ่มต้นมีประโยชน์ในบางวิธีและเฉพาะที่สำคัญ ตัวอย่างเช่นพวกเขาทำประเภทพร้อมต่อเนื่อง
Robert Harvey

6
ลายเซ็น ctor เฉพาะอาจมีประโยชน์ ตัวอย่างเช่นหากตัวแปรประเภทของคุณถูก จำกัด ให้เป็น Collection <T> ด้วย ctor ของ T (Collection <T>) คุณรู้ว่าคุณสามารถสร้างคอลเลกชันใหม่ที่ได้รับอีก ไม่ว่าประโยชน์นั้นมีค่ากับความซับซ้อนเป็นพิเศษหรือไม่ก็เป็นคำถาม
Phoshi

คำตอบ:


5

สำหรับคำตอบที่มีสิทธิ์ฉันจะแนะนำคุณกับคำตอบของ Eric Lippert สำหรับคำถามนั้นใน StackOverflow เมื่อไม่กี่ปีที่ผ่านมาซึ่งเป็นข้อมูลโค้ดที่อ้างถึงสั้น ๆ ด้านล่าง

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

...

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


2
ข้อความที่นำมาจากบริบทนั้นทำให้เข้าใจผิดมาก มันแสดงให้เห็นว่าอีริคคิดว่าไมโครซอฟท์น่าจะ "ไปตลอดทาง" ซึ่งไม่ใช่ตำแหน่งของเขาเลย ในความเป็นจริงเขาตรงกับคุณสมบัติที่เสนอ
Robert Harvey

1
ขอบคุณนี่จะตอบคำถามของฉันบางส่วน: ใกล้ถึงจุดสิ้นสุดของคำตอบของเขา Eric Lippert กล่าวว่ามันเป็นข้อ จำกัด ของ IL และการรวมคุณสมบัตินี้จะต้องมีการเพิ่มไปยัง IL มันต้องการจะสมบูรณ์แบบถ้าคุณสามารถให้แหล่งที่มากับสิ่งที่ IL ถูกสร้างขึ้นเพื่อเป็นส่วนหนึ่งที่จะนำมาใช้ - นั่นคือโดยทั่วไปเรียกคอนสตรัคเริ่มต้น
Theodoros Chatzigiannakis

@TheodorosChatzigiannakis: ทำไมคุณไม่ยิงDecompiler ของ Telerikและค้นหาด้วยตัวเองล่ะ?
Robert Harvey

2
@ RobertHarvey ฉันไม่คิดว่ามันจะแนะนำตำแหน่งสำหรับเขาเลย แต่ฉันได้รวมข้อความเพิ่มเติมเพื่อเน้นตำแหน่งของเขา
Chris Hannon

1
อืม, F # มีวิธีการล่วงหน้ามากขึ้นในการ จำกัด ประเภทเช่นการตรวจสอบเป็นเวลารวบรวมถ้าชั้นมีผู้ประกอบการ บางที F # ต้องการระบบข้อ จำกัด ที่มีประสิทธิภาพมากกว่า C # เนื่องจากการตรวจสอบประเภทที่เข้มงวดมาก อย่างไรก็ตามภาษานี้สามารถใช้วิธีการขั้นสูงเพื่อคงคลาสบน. Net Framework
OnesimusUnbound

16

การถอดรหัส (ตามคำแนะนำของ Robert Harvey) ให้ผลดังต่อไปนี้สำหรับทุกคนที่สนใจ วิธีนี้:

static T GenericMake<T>()
    where T : new()
{
    return new T();
}

เห็นได้ชัดว่าเมื่อรวบรวมจะกลายเป็นสิ่งนี้:

private static T GenericMake<T>()
    where T : new()
{
    T t;
    T t1 = default(T);
    if (t1 == null)
    {
        t = Activator.CreateInstance<T>();
    }
    else
    {
        t1 = default(T);
        t = t1;
    }
    return t;
}
  • ถ้าTเป็นประเภทค่าจะกลายเป็นnew()default(T)
  • ถ้าTเป็นประเภทอ้างอิงnew()ทำงานโดยใช้การสะท้อน สายภายในActivator.CreateInstance()RuntimeType.CreateInstanceDefaultCtor()

ดังนั้นจึงเป็น - ภายในตัวสร้างเริ่มต้นจริงๆพิเศษกับ C # ที่เกี่ยวข้องกับ CLR การให้ผู้สร้างรายอื่นได้รับการปฏิบัติแบบเดียวกันจะมีค่าใช้จ่ายสูงถึงแม้ว่าจะมีบางกรณีการใช้งานที่ถูกต้องสำหรับข้อ จำกัด ที่ซับซ้อนมากขึ้นในข้อมูลทั่วไป


4
น่าสนใจ ทำไมการเรียกซ้ำdefault(T) สำหรับประเภทค่า
Avner Shahar-Kashtan

2
@ AvnerShahar-Kashtan ฉันไม่รู้ มันอาจจะเป็นสิ่งประดิษฐ์ของกระบวนการรวบรวม / ถอดรหัสเช่นtตัวแปร (ซึ่งสามารถถูกแทนที่ด้วยreturnคำสั่งซ้อนกัน)
Theodoros Chatzigiannakis
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.