วิธีการขยายและวัตถุแบบไดนามิก


97

ฉันจะสรุปปัญหาของฉันเป็นข้อมูลโค้ดต่อไปนี้

List<int> list = new List<int>() { 5, 56, 2, 4, 63, 2 };
Console.WriteLine(list.First());

โค้ดด้านบนใช้งานได้ดี

ตอนนี้ฉันลองทำสิ่งต่อไปนี้แล้ว

dynamic dList = list;
 Console.WriteLine(dList.First());

แต่ฉันได้รับ RuntimeBinderException ทำไมจึงเป็นเช่นนั้น


ดูเหมือนจะซ้ำกับคำถามนี้ที่ถามเมื่อ 4 วันที่แล้วstackoverflow.com/questions/5270782/…
jbtule

@jbtule ความแตกต่างคือthisไดนามิกที่นี่ แต่ถ้าคุณมาที่นี่คุณก็น่าจะดูคำถามนั้นเช่นกัน
nik.shornikov

คำตอบ:


131

หากต้องการขยายคำตอบของ Stecya ... วิธีการขยายไม่รองรับการพิมพ์แบบไดนามิกในรูปแบบของวิธีการขยายเช่นเรียกว่าเป็นวิธีการอินสแตนซ์ อย่างไรก็ตามสิ่งนี้จะได้ผล:

dynamic dList = list;
Console.WriteLine(Enumerable.First(dList));

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


ฉันกำลังเล่นกับวัตถุไดนามิกและได้รับข้อยกเว้นนี้คุณเคยเขียนบทความเกี่ยวกับหัวข้อนี้หรือไม่ใช้หรือไม่ใช้วัตถุไดนามิกที่ไหน
santosh singh

19
@geek: โดยส่วนตัวแล้วกฎทั่วไปของฉันคือใช้เฉพาะในdynamicที่ที่คุณต้องการจริงๆเท่านั้น ... โดยพื้นฐานแล้วถ้าคุณจะเข้าถึงสมาชิกด้วยการไตร่ตรองนั่นเป็นสัญญาณสำคัญ ในทางกลับกันฉันเป็นคนพิมพ์ดีดที่ตายยากคนอื่นอาจแนะนำนโยบายในแง่ร้ายน้อยลง :)
Jon Skeet

2
อาจอ่านได้ง่ายกว่าในการส่งกลับไปยังประเภท know ซึ่งใช้งานได้: Console.WriteLine (((List <int>) dList) .First ()); หรือ Console.WriteLine ((dList as List <int>) .First ()) ;.
AVee

142

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

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


ขอบคุณมากสำหรับคำอธิบาย
santosh singh

3
คุณลักษณะดังกล่าวอยู่ในการเดินทางหรือไม่? แน่นอนมันจะเป็นการเปลี่ยนแปลงที่รุนแรง การโทรที่กำลังขว้าง RunTimeBinderExceptions จะเริ่มทำงานทันทีเมื่อคอมไพล์ซอร์สใหม่ นอกจากนี้จะมีความเสี่ยงด้านความปลอดภัยที่เกี่ยวข้องกับการใช้คุณลักษณะดังกล่าวหรือไม่?
Ani

5
@ani: เรากำลังวางแผนที่จะใช้คุณลักษณะนั้นหรือไม่? เลขที่มีความเสี่ยงใด ๆ ฉันไม่รู้; คุณมีความเสี่ยงด้านความปลอดภัยประเภทใดอยู่ในใจ เริ่มต้นด้วยการบอกว่าใครเป็นผู้โจมตีและสิ่งที่คุกคามผู้ใช้
Eric Lippert

@EricLippert ฉันเข้าใจว่าdynamicวัตถุทั้งหมดมีค่าเท่ากับ C #: DynamicObjectดังนั้นจึงไม่มีวิธีที่จะแยกความแตกต่างและเป็นสาเหตุหนึ่งที่ไม่สามารถเพิ่มวิธีการขยายได้dynamicใช่หรือไม่
Tom Sarduy

@EricLippert พิจารณาขยายคำตอบนี้อีกเล็กน้อยและเพิ่มประโยคตามบรรทัดของ "เมื่อพารามิเตอร์ใด ๆเป็นแบบไดนามิกความละเอียดทั้งหมดจะถูกเลื่อนออกไปจนถึงรันไทม์" แม้ว่าคุณจะเห็นได้ชัดว่าบิตที่สำคัญนี้ยากที่จะหาได้จากที่อื่นใน SO (ดูstackoverflow.com/questions/48324768เป็นต้น)
Alexei Levenkov

18

เพราะไม่ได้เป็นวิธีการของFirst() Listถูกกำหนดไว้ใน Linq Extension ถึงIEnumerable<>

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