เหตุใดจึงไม่อนุญาตให้ 'void' เป็นประเภททั่วไปใน C #


53

อะไรคือการตัดสินใจในการออกแบบที่แย้งว่าvoidไม่สามารถสร้างได้และไม่ได้รับอนุญาตให้เป็นประเภททั่วไป? structท้ายที่สุดมันก็ว่างเปล่าเป็นพิเศษและจะหลีกเลี่ยง PITA โดยรวมที่มีความแตกต่างFuncและActionผู้ได้รับมอบหมาย

(C ++ อนุญาตให้voidส่งคืนอย่างชัดเจนและอนุญาตให้voidเป็นพารามิเตอร์เทมเพลต)


13
@Oded พิจารณาว่าEric Lippert มีบัญชีและเข้าร่วมในโปรแกรมเมอร์ฉันคิดว่าเขาเพิ่งทำ
โธมัสโอเวนส์

2
@BenVoigt ไม่จำเป็นต้องมีความรู้ของแต่ละบุคคลแม้ว่าจะมีคนเพียงคนเดียวที่สามารถ (ได้อย่างง่ายดายฉันจะสมมติ) ให้คำตอบที่ถูกต้อง ใครก็ตามที่คุ้นเคยกับข้อมูลจำเพาะอาจตอบคำถามได้โดยเฉพาะอย่างยิ่งหากพวกเขามีความรู้ในการออกแบบภาษาโปรแกรม นอกจากนี้ยังเป็นคำถามเกี่ยวกับการใช้ภาษา / การออกแบบภาษาที่น่าสนใจซึ่งอยู่ในหัวข้อที่นี่
โธมัสโอเวนส์

6
@BenVoigt: ทำไมคุณถึงกระตือรือร้นที่จะมีคำถามที่ถูกต้องและน่าสนใจอย่างสมบูรณ์แบบปิดโดยไม่มีเหตุผลที่ดีอื่น ๆ เพื่อตอบสนองความ pedantry ของคุณเอง? ฉันค้นหาและไม่สามารถหาคำตอบได้ อาจมีบางคนที่นี่ได้อ่านบล็อกโพสต์เกี่ยวกับเรื่องนี้บางทีคนที่ตัดสินใจเลือกต้องการตอบคำถามอาจมีบางคนคุยกับคนที่ตัดสินใจเกี่ยวกับเรื่องนี้และถามคำถามด้วยตนเองและสามารถตอบคำถามได้ ฉันหยุดโพสต์ในเว็บไซต์นี้และสวยมากเพราะคนดูสนใจที่จะรับคำถามมากกว่าการตอบคำถาม

4
ฉันสามารถชี้ให้เห็นคำถามและคำตอบ "จุดใหญ่" ที่นี่และโดยเฉพาะอย่างยิ่งใน SO ทั่วไปของรูปแบบ "ไวยากรณ์นี้หมายความว่าอย่างไร? คำถามเหล่านั้นแทบจะไม่เคยถูกปิดเพราะทุกคนสามารถกองและปล่อยคำจำกัดความสำหรับตัวชี้ const เพื่อวัตถุ const คำถามที่น่าสนใจยิ่งกว่านี้ที่ทำให้แทร็กที่ถูกตีได้รับการล่ามจากเว็บไซต์ด้วยเหตุผลบางประการ: อย่างจริงจังมันเป็นเพียงไม่กี่กิโลไบต์ในคลังข้อมูลที่ไหนสักแห่ง เราทุกคนสามารถผ่อนคลายและยอมรับการเรียนรู้ได้มากกว่าการตีความกฎเกณฑ์โดยพลการซึ่งมีจุดประสงค์น้อยมากหรือไม่?

2
@ThomasOwens: ฉันมีความกระตือรือร้นในไซต์นี้มากกว่า SO ในเว็บไซต์นี้ฉันโพสต์คำตอบเกี่ยวกับคำถามหนึ่งข้อในทุกๆ 300 ข้อบนดังนั้นฉันโพสต์คำตอบเกี่ยวกับคำถามหนึ่งข้อในทุก ๆ 1,500 ความแตกต่างในกิจกรรมจำนวนคำตอบที่แท้จริงนั้นเป็นโอกาสที่สูงขึ้นมาก ตอบคำถาม C # ใน SO
Eric Lippert

คำตอบ:


69

ปัญหาพื้นฐานกับ "โมฆะ" คือมันไม่ได้หมายความว่าสิ่งเดียวกันกับประเภทผลตอบแทนอื่น ๆ "void" หมายถึง "ถ้าวิธีนี้คืนค่ามันจะคืนค่าใด ๆ " ไม่เป็นโมฆะ; null เป็นค่า มันจะไม่ส่งกลับค่าใด ๆ

สิ่งนี้จะทำให้ระบบการพิมพ์สับสน ประเภทของระบบเป็นหลักระบบสำหรับการหักลอจิคัลเกี่ยวกับการดำเนินงานที่ถูกต้องในค่าเฉพาะ; วิธีการคืนค่าเป็นโมฆะไม่ส่งคืนค่าดังนั้นคำถาม "การดำเนินการใดที่ใช้ได้กับสิ่งนี้" ไม่สมเหตุสมผลเลย ไม่มี "สิ่ง" สำหรับการดำเนินการที่ถูกต้องหรือไม่ถูกต้อง

ยิ่งไปกว่านั้นสิ่งนี้จะทำให้บางสิ่งบางอย่างดุร้ายขึ้น รันไทม์. NET คือการนำระบบปฏิบัติงานเสมือนมาใช้ซึ่งระบุว่าเป็นเครื่องซ้อน นั่นคือเครื่องเสมือนที่มีการดำเนินการทั้งหมดในแง่ของผลกระทบต่อกองการประเมินผล (แน่นอนในทางปฏิบัติเครื่องจะถูกนำไปใช้กับเครื่องที่มีทั้งสแต็กและรีจิสเตอร์ แต่ระบบปฏิบัติการเสมือนถือว่าเป็นเพียงสแต็ก) ผลของการเรียกใช้วิธีการโมฆะนั้นเป็นพื้นฐานแตกต่างจากผลกระทบของการเรียกไปยังวิธีการไม่เป็นโมฆะ; วิธีการที่ไม่เป็นโมฆะมักจะวางบางสิ่งบางอย่างบนสแต็กซึ่งอาจต้องมีการเปิดออก วิธีการโมฆะไม่เคยใส่อะไรในกอง และดังนั้นคอมไพเลอร์ไม่สามารถรักษาโมฆะและวิธีที่ไม่เป็นโมฆะเหมือนกันในกรณีที่ค่าส่งคืนของวิธีการจะถูกละเว้น; หากวิธีการนั้นเป็นโมฆะก็จะไม่มีค่าตอบแทนดังนั้นจะต้องไม่มีป๊อป

ด้วยเหตุผลเหล่านี้ "โมฆะ" ไม่ใช่ประเภทที่สามารถสร้างอินสแตนซ์ได้ มันไม่มีค่านั่นคือประเด็นทั้งหมด มันไม่สามารถแปลงเป็นวัตถุและวิธีการคืนค่าเป็นโมฆะไม่เคยได้รับการปฏิบัติ polymorphically ด้วยวิธีการไม่กลับเป็นโมฆะเพราะการทำเช่นนั้นจะทำลายกอง!

ดังนั้นโมฆะไม่สามารถใช้เป็นอาร์กิวเมนต์ชนิดซึ่งเป็นความอัปยศตามที่คุณทราบ มันจะสะดวกมาก

ด้วยประโยชน์ของการเข้าใจถึงปัญหาหลังเหตุการณ์มันจะดีกว่าสำหรับทุกคนที่เกี่ยวข้องหากไม่มีอะไรเลยวิธีการคืนค่าเป็นโมฆะจะส่งคืน "หน่วย" ซึ่งเป็นประเภทอ้างอิงเดี่ยวที่มีมนต์ขลังโดยอัตโนมัติ จากนั้นคุณจะรู้ว่าการเรียกใช้เมธอดทุกวิธีทำให้บางสิ่งบางอย่างบนสแต็กคุณจะรู้ว่าการเรียกเมธอดทุกวิธีส่งคืนสิ่งที่สามารถกำหนดให้กับตัวแปรชนิดของวัตถุและแน่นอนว่าหน่วยสามารถใช้เป็นอาร์กิวเมนต์ชนิดได้ ไม่จำเป็นต้องมีประเภทผู้แทน Action และ Func แยกกัน น่าเศร้าที่ไม่ใช่โลกที่เราอยู่

สำหรับความคิดเพิ่มเติมในหลอดเลือดดำนี้ดู:


C ++ รองรับได้โดยไม่ต้องใช้เวทมนต์ชนิดเดี่ยว แต่ฉันคิดว่ามันเกี่ยวข้องกับ C ++ โดยใช้สไตล์ "generics" ที่แตกต่างอย่างสิ้นเชิงจากนั้น C #
Winston Ewert

4
@WinstonEwert - ฉันค่อนข้างแน่ใจว่า C ++ ไม่สนับสนุน generics เลย แต่มีเทมเพลตซึ่งแตกต่างกันโดยพื้นฐาน ดังที่ฉันเข้าใจแล้วด้วยเทมเพลตคอมไพเลอร์กำลังทำการค้นหาทั่วโลกและแทนที่ด้วยพารามิเตอร์ประเภทของคุณ แต่ด้วย generics ระบบประเภทกำลังสร้างประเภทที่เหมาะสม ฉันยังคิดว่านั่นเป็นสาเหตุที่ข้อผิดพลาดแม่แบบ C ++ นั้นป้านมาก ฉันแน่ใจว่า Eric จะแก้ไขให้ถูกต้องหากฉันพูดอะไรที่ไม่ถูกต้อง
Adam Rackis

1
ฉันคิดว่าโครงสร้างทั้งหมดได้รับการจัดการในเวลารวบรวมเพื่อให้ได้ตำแหน่งที่เหมาะสมในสแต็กและในที่อื่น ๆ ที่มีการแทรก ดังนั้นVoidควรจะโอเคที่จะส่งผ่านเป็นจำนวนอาร์กิวเมนต์ภายใน 0 สแต็กไบต์ เมื่อโครงสร้างใด ๆ จำเป็นต้องแปลงเป็นobjectหรือเรียกใช้เมธอด (เพื่อรับthis) มันจะถูกวางไว้บน heap พร้อมกับTypeใส่การอ้างอิงไว้ก่อนพื้นที่ของหน่วยความจำ (สำหรับการใช้งาน CLR จำนวนมาก) และสามารถจัดการได้อย่างเหมาะสม สำหรับฉันพิมพ์เป็นเพียงการจับกลุ่มของวัตถุที่สามารถแยกแยะได้โดยลักษณะบางอย่าง (เขตข้อมูล) Voidเป็นเพียงวัตถุเดียว
ony

1
@ OlivierJacot-Descombes: หากvoidเป็นประเภทค่าที่ว่างเปล่าคำสั่งนั้นจะแปลเป็นศูนย์คำแนะนำของรหัสเครื่อง ไม่ได้มีประโยชน์มากสำหรับประเภทฮาร์ดโค้ดVoidแต่มีประโยชน์ในกรณีที่ประเภทมีพารามิเตอร์ทั่วไปหลายรายการ แต่บางประเภทไม่จำเป็นต้องใช้ในบางกรณี
supercat

2
@EricLippert: การจัดการค่าส่งคืนประเภทค่าที่เหมาะสมจะต้องใช้ความสามารถในการป๊อปจำนวนตัวแปรของคำออกจากสแต็ก จะมีปัญหาพื้นฐานหรือไม่ที่จะอนุญาตให้จำนวนคำเป็นศูนย์? หากผู้เรียกรับผิดชอบในการจัดสรรพื้นที่และส่งผ่านไบต์ระบบจะต้องรับรู้ว่าการโมฆะเป็นโมฆะไม่มีความหมายและอาจไม่ถือว่าคุ้มค่ากับความพยายาม แต่ฉันไม่เห็นปัญหา "พื้นฐาน" ใด ๆ .
supercat

9

จาก: http://connect.microsoft.com/VisualStudio/feedback/details/94226/allow-void-to-be-parameter-of-generic-class-if-not-in-c-then-just-in- รันไทม์

นี่คือการออกแบบจริง - เราไม่อนุญาตให้มีตัวอย่างประเภท void (รวมถึงประเภทอื่น ๆ ใน runtime) คุณไม่สามารถสร้างเป็นโมฆะหรือเป็นโมฆะ [] อย่างใดอย่างหนึ่ง เราเสียบรูชนิดเหล่านี้เพื่อความปลอดภัย

ฉันทำไม่ได้สำหรับชีวิตของฉันที่เห็นว่าช่องว่างเป็นช่องโหว่ แต่ ... มันพูดอย่างนั้น

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