Sepertinya Anda memilih untuk membebani terminologi "namespace" dan "modul." Seharusnya tidak mengherankan bahwa Anda melihat sesuatu sebagai "tidak langsung" ketika mereka tidak sesuai dengan definisi Anda.
Di sebagian besar bahasa yang mendukung ruang nama, termasuk C #, namespace bukan modul. Namespace adalah cara pelingkupan nama. Modul adalah cara pelingkupan perilaku.
Secara umum, sementara .Net runtime mendukung gagasan modul (dengan definisi yang sedikit berbeda dari yang Anda gunakan secara implisit), itu agak jarang digunakan; Saya hanya melihatnya digunakan dalam proyek yang dibangun di SharpDevelop, sebagian besar sehingga Anda dapat membangun DLL tunggal dari modul yang dibangun dalam bahasa yang berbeda. Sebagai gantinya, kami membangun perpustakaan menggunakan perpustakaan yang terhubung secara dinamis.
Dalam C #, namespaces menyelesaikan tanpa "lapisan tipuan" selama mereka semua dalam biner yang sama; tipuan apa pun yang diperlukan adalah tanggung jawab kompiler dan tautan yang tidak perlu Anda pikirkan. Setelah Anda mulai membangun proyek dengan banyak dependensi, Anda kemudian merujuk pustaka eksternal. Setelah proyek Anda membuat referensi ke perpustakaan eksternal (DLL), kompiler menemukannya untuk Anda.
Dalam Skema, jika Anda perlu memuat pustaka eksternal, Anda harus melakukan sesuatu seperti (#%require (lib "mylib.ss"))
pertama, atau menggunakan antarmuka fungsi asing secara langsung, seingat saya. Jika Anda menggunakan binari eksternal, Anda memiliki jumlah pekerjaan yang sama untuk menyelesaikan binari eksternal. Kemungkinannya, Anda sebagian besar telah menggunakan pustaka yang sangat umum digunakan sehingga ada shim berbasis Skema yang mengabstraksikan itu dari Anda, tetapi jika Anda harus menulis integrasi Anda sendiri dengan pustaka pihak ketiga, pada dasarnya Anda harus melakukan beberapa pekerjaan untuk "memuat " Perpustakaan.
Di Ruby, Modul, Ruang nama, dan Nama File sebenarnya jauh lebih sedikit terhubung daripada yang Anda duga; LOAD_PATH membuat segalanya menjadi sedikit rumit, dan deklarasi Modul bisa di mana saja. Python mungkin lebih dekat untuk melakukan hal-hal seperti yang Anda pikir Anda lihat di Skema, kecuali bahwa perpustakaan pihak ke-3 di C masih menambahkan kerutan (kecil).
Selain itu, bahasa yang diketik secara dinamis seperti Ruby, Python dan Lisp biasanya tidak memiliki pendekatan yang sama dengan "kontrak" seperti bahasa yang diketik secara statis. Dalam bahasa yang diketik secara dinamis, Anda biasanya hanya membuat semacam "persetujuan Gentleman" bahwa kode akan menanggapi metode tertentu, dan jika kelas Anda tampaknya berbicara dalam bahasa yang sama, semuanya baik. Bahasa yang diketik secara statis memiliki mekanisme tambahan untuk menegakkan aturan-aturan ini pada waktu kompilasi. Dalam C #, menggunakan kontrak semacam itu memungkinkan Anda untuk memberikan setidaknya setidaknya jaminan kepatuhan yang cukup berguna untuk antarmuka ini, yang memungkinkan Anda untuk membundel plugins dan substitusi dengan beberapa derajat jaminan kesamaan karena Anda semua mengkompilasi terhadap kontrak yang sama. Di Ruby atau Skema, Anda memverifikasi perjanjian ini dengan menulis tes yang berfungsi saat runtime.
Ada manfaat kinerja yang dapat diukur dari jaminan waktu kompilasi ini, karena pemanggilan metode tidak memerlukan pengiriman ganda. Untuk mendapatkan manfaat ini dalam sesuatu seperti Lisp, Ruby, JavaScript, atau di tempat lain, apa yang sekarang masih merupakan mekanisme eksotis dari kelas kompilasi statis tepat waktu dalam VM khusus diperlukan.
Satu hal yang ekosistem C # masih memiliki dukungan yang relatif belum matang adalah pengelolaan dependensi biner ini; Java telah memiliki Maven selama beberapa tahun untuk memastikan Anda memiliki semua dependensi yang diperlukan, sedangkan C # masih memiliki pendekatan seperti MAKE yang cukup primitif yang melibatkan penempatan file secara strategis di tempat yang tepat sebelumnya.