ข้อบกพร่องของการใช้ประเภทไดนามิกใน C #


14

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

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

คำถาม,

มีข้อบกพร่องใด ๆ ที่เฉพาะเจาะจงนอกเหนือจากการเรียกใช้วิธีการแบบไดนามิกที่ไม่ถูกต้องซึ่งโยนข้อยกเว้นเวลาทำงานที่นักพัฒนาต้องรู้ก่อนเริ่มการใช้งานหรือไม่


3
ใน C # 3 ฉันมักจะพิจารณาการใช้objectหรือการพิมพ์แบบโดยตรงเพื่อใช้เป็นรหัสกลิ่น ในเกือบทุกกรณีหมายความว่าฉันหรือหนึ่งในทีมของฉันไม่ได้ออกแบบอินเทอร์เฟซที่เหมาะสมสำหรับฟังก์ชันการทำงานนั้น ฉันเดาว่าถ้าฉันใช้ C # 4 ตอนนี้ฉันก็จะรู้สึกแบบเดียวกับการใช้dynamicด้วย ฉันเห็นกรณีนี้หากคุณทำให้ทุกอย่างเป็นแบบไดนามิก แต่ในกรณีนั้นคุณอาจเลือกภาษาที่พิมพ์แบบไดนามิกในตอนแรก * 8 ')
ทำเครื่องหมายบูธ

@ MarkBooth +1 สำหรับมุมมอง มันปลอดภัยแล้วหรือยังที่จะบอกว่าการใช้งานหลักที่ใช้ C # ยังคงเป็นประเภทที่มีการแนะนำอย่างยิ่งแม้จะมีการแนะนำประเภทไดนามิกใน 4.0
Karthik Sreenivasan

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

@EdJames - เสียงที่เหมือนการใช้งานที่ดีของการdynamicบวกฉันหวังว่าฉันเคยรู้จักกันเกี่ยวกับ IronPython เมื่อฉันถูกพัฒนากับสุทธิ - มันจะได้ทำบางสิ่งบางอย่างที่เรากำลังพยายามที่จะทำมากได้ง่ายขึ้น
Mark Booth

คำตอบ:


16

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

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

มี IMO เหตุผลน้อยมากที่จะใช้การพิมพ์แบบไดนามิกใน C #, หลักที่เป็นความร่วมมือกับภาษาที่พิมพ์แบบไดนามิก (ซึ่งเป็น AFAIK เหตุผลที่มีการแนะนำแบบไดนามิกในตอนแรก)

หากคุณต้องการเขียนโปรแกรมแบบไดนามิกอย่างสมบูรณ์คุณควรดูภาษาที่ออกแบบมาให้เป็นแบบไดนามิกไม่ใช่แฮ็ก C # ให้เป็นแบบไดนามิก คุณสามารถใช้ตัวอย่างเช่นIronPythonหากคุณต้องการใช้ไลบรารี. Net


+1 สำหรับ IronPython ซึ่งหมายความว่าอาจนำไปสู่ปัญหาการบำรุงรักษาในระยะยาว
Karthik Sreenivasan

6
สิ่งใหญ่ที่dynamicช่วยให้คุณมีความสามารถในการโยนวัตถุให้เป็นวัตถุจริงโดยไม่ต้องมีการแฮ็กการสะท้อนใด ๆ ตัวอย่างเช่นถ้าBase foo = new Derived();และมีสองวิธีที่มากเกินไปMoo(Base x)และMoo(Derived x)แล้วMoo(foo)เรียกMoo(Base x)แต่โทรMoo((dynamic)foo) Moo(Derived x)สิ่งนี้นำไปสู่การปรับใช้รูปแบบผู้เข้าชมที่หรูหรามากเช่น: code.logos.com/blog/2010/03/…และโดยทั่วไปเป็นเทคนิคที่ทรงพลังมาก

@TheMouthofaCow Nice มีการใช้ "ถูกต้องตามกฎหมาย" อื่น ๆ สำหรับไดนามิกเช่นกันอย่างไรก็ตามสิ่งเหล่านี้มีอยู่ไม่มากและอยู่ไกลระหว่างกัน (และแน่นอนคุณต้องรู้ว่าคุณกำลังทำอะไรอยู่ก่อนจะลองทำอะไรแบบนี้)
MatějZábský

@ TheMouthofaCow รูปแบบการออกแบบที่ค่อนข้างใหม่ (The Visitor Pattern) ที่ควรทราบ ขอบคุณ
Karthik Sreenivasan

1
ใช่มันเจ๋งมาก ฉันมาด้วยตัวเองเมื่อสัปดาห์ที่แล้วดังนั้นมันจึงเป็นเรื่องดีที่ได้เห็นว่ามันเป็นความคิดที่ได้รับการยอมรับซึ่งถูกนำไปใช้กับอาร์เซนอล C #

9

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

  1. วิธีการส่วนขยายไม่ทำงาน นี่น่าจะเป็นอันที่ใหญ่ที่สุด ถ้าคุณมีคุณจะไม่สามารถใช้รหัสเช่นdynamic collection collection.Distinct()นั่นเป็นเพราะวิธีการขยายที่มีอยู่ขึ้นอยู่กับ namespace usings และ DLR ไม่มีทางรู้ได้

    Enumerable.Distinct(collection)ในฐานะที่เป็นวิธีแก้ปัญหาที่คุณสามารถเรียกใช้วิธีการที่ราวกับว่ามันเป็นวิธีการที่คงปกติ: IEnumerable<dynamic>หรือคุณสามารถเปลี่ยนชนิดของคอลเลกชันเพื่อสิ่งที่ต้องการ

  2. foreachIEnumerableต้อง ใน C # ปกติforeachจะขึ้นอยู่กับรูปแบบ นั่นคือมันไม่ต้องการอินเทอร์เฟซเฉพาะใด ๆ เพียงGetEnumerator()วิธีการที่ส่งกลับวัตถุที่เหมาะสม ถ้าคุณใช้foreachในdynamicการดำเนินงานของIEnumerableเป็นสิ่งจำเป็น แต่เนื่องจากสาเหตุของพฤติกรรมนี้คือ C # 1.0 ไม่มีข้อมูลทั่วไปการ "ข้อบกพร่อง" นี้ค่อนข้างไม่เกี่ยวข้องเลย


วิธี +1 สำหรับส่วนขยาย สิ่งนี้ยังใช้กับตัวดำเนินการค้นหา LINQ อื่น ๆ เช่น GroupBy () หรือไม่
Karthik Sreenivasan

2
@Karthik: ใช่แล้ว ฉันคิดว่าวิธีการต่อเติมเป็นเวลารวบรวมน้ำตาล syntactic ดังนั้นความจริงที่ว่าพวกเขาไม่ได้รับการแก้ไข

@TheMouthofaCow +1 - ขอบคุณสำหรับการชี้แจง
Karthik Sreenivasan

1
ฉันเห็นด้วยกับวิธีการขยายนั่นคือวิธีที่ไดนามิกไม่สามารถหาวิธีการขยายในเวลาทำงาน แต่ฉันไม่สามารถติดตามการรวบรวมแบบไดนามิกที่คุณได้อธิบายไว้
Karthik Sreenivasan

7

ปัญหาเกี่ยวกับประเภทไดนามิก (ไม่ใช่ตัวแปรที่ประกาศว่าเป็นแบบไดนามิก) ใน. net คือพวกเขาไม่มีฟังก์ชั่นที่พร้อมใช้งานสำหรับประเภทสแตติกมากมาย

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

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


6

เนื่องจากdynamicเป็นเพียงการทำเครื่องหมายobjectว่ามันเป็นกล่องประเภทค่า

สิ่งนี้อาจมีผลกระทบด้านประสิทธิภาพ แต่เนื่องจากฉันใช้การพิมพ์แบบคงที่ในโค้ดที่มีประสิทธิภาพที่สำคัญต่อไปนั่นอาจไม่ใช่ปัญหาในทางปฏิบัติ

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


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