Mengapa “menggunakan Sistem;” tidak dianggap praktik buruk?

47

Saya memiliki latar belakang C ++ dan saya sepenuhnya memahami dan setuju dengan jawaban atas pertanyaan ini: Mengapa “menggunakan namespace std;” dianggap praktik yang buruk?

Jadi saya heran bahwa, setelah memiliki pengalaman dengan C # sekarang, saya melihat kebalikannya di sana: using Some.Namespace;secara harfiah digunakan di mana-mana. Setiap kali Anda mulai menggunakan suatu tipe, Anda menambahkan direktif penggunaan untuk namespace-nya terlebih dahulu (jika belum ada di sana). Saya tidak ingat pernah melihat file .cs-file yang tidak dimulai dengan using System; using System.Collections.Generic; using X.Y.Z; etc.... Bahkan, jika Anda menambahkan file baru melalui wizard Visual Studio, secara otomatis menambahkan beberapa menggunakan arahan di sana, meskipun Anda mungkin tidak membutuhkannya sama sekali. Jadi, sementara di komunitas C ++ Anda pada dasarnya digantung, C # bahkan mendorong untuk melakukan ini. Setidaknya begini tampilannya bagiku.

Sekarang, saya mengerti bahwa menggunakan arahan dalam C # dan C ++ tidak persis sama. Juga, saya mengerti bahwa salah satu hal paling using namespacejahat yang dapat Anda lakukan di C ++, yaitu meletakkannya di file header, tidak memiliki padanan yang jahat di C # karena kurangnya konsep file header dan #include.

Namun, terlepas dari perbedaan mereka, menggunakan arahan dalam C # dan C ++ melayani tujuan yang sama, yang hanya harus mengetik SomeTypesepanjang waktu, daripada yang lebih lama Some.Namespace.SomeType(dalam C ++ dengan ::alih - alih .). Dan dengan tujuan yang sama ini, bahaya juga tampak sama bagi saya: penamaan tabrakan.

Dalam kasus terbaik ini menghasilkan kesalahan kompilasi, jadi Anda "hanya" harus memperbaikinya. Dalam kasus terburuk, masih dikompilasi dan kode diam-diam melakukan hal-hal yang berbeda dari yang Anda inginkan. Jadi pertanyaan saya adalah: Mengapa (tampaknya) menggunakan arahan yang dianggap sangat buruk di C # dan C ++?

Namun, beberapa ide jawaban yang saya miliki (tidak satupun yang benar-benar memuaskan saya):

  • Ruang nama cenderung jauh lebih lama dan lebih banyak bersarang di C # daripada di C ++ ( stdvs. System.Collection.Generic). Jadi, ada lebih banyak keinginan dan lebih banyak keuntungan dalam menghilangkan kode dengan cara ini. Tetapi bahkan jika ini benar, argumen ini hanya berlaku ketika kita melihat ruang nama standar. Yang khusus dapat memiliki nama pendek apa pun yang Anda suka, baik dalam C # dan C ++.

  • Ruang nama tampaknya jauh lebih "butiran halus" di C # daripada di C ++. Sebagai contoh, di C ++ seluruh perpustakaan standar terkandung dalam std(ditambah beberapa ruang nama bersarang kecil seperti chrono) sementara di C # Anda memiliki System.IO, System.Threading, System.Textdll Jadi, risiko memiliki tabrakan penamaan lebih kecil. Namun, ini hanya firasat. Sebenarnya saya tidak menghitung berapa banyak nama yang Anda "impor" dengan using namespace stddan using System. Dan lagi, bahkan jika ini benar, argumen ini hanya berlaku ketika melihat ruang nama standar. Yang Anda miliki sendiri dapat dirancang sebagai butiran halus sesuai keinginan, baik dalam C # maupun C ++.

Apakah ada lebih banyak argumen? Saya terutama tertarik pada fakta-fakta nyata yang sebenarnya (jika ada) dan tidak begitu banyak pendapat.

sebrockm
sumber
2
@Timo OP secara eksplisit tidak bertanya tentang polusi tajuk.
Konrad Rudolph
1
Saya berasumsi itu karena tidak ada persaingan untuk namespace global ke tingkat yang sama yang ada di C ++ (terutama karena perpustakaan standar C). Tetapi saya menunggu jawaban dari mereka yang paling tahu.
Wyck
2
@ ThomasWeller Dalam C ++ sudah jelas. Dalam C # pertimbangkan metode ekstensi dengan Ext(this T t, long l)yang dipanggil via t.Ext(0). Jika Anda kemudian menambahkan namespace lain yang berisi metode ekstensi Ext(this T t, int i), yang itu akan dipanggil. Tapi saya bukan ahli C # (belum).
sebrockm
2
@ Franck bahkan jika saya memberi Anda titik itu, maka argumen yang sama berlaku untuk C ++, lebih lanjut mendorong pertanyaan saya untuk tidak melihat perbedaan antara C ++ dan C #
sebrockm
3
@ Franck C ++ akan melemparkan kesalahan kompiler pada Anda dalam kasus ambiguitas. Serta C #.
Timo

Jawaban:

28

Mengapa “menggunakan Sistem;” tidak dianggap praktik buruk?

"menggunakan Sistem;" adalah tidak universal tidak dianggap sebagai praktek yang buruk. Lihat misalnya: Mengapa Anda tidak menggunakan arahan 'using' di C #?

Tapi itu mungkin benar bahwa itu tidak dianggap cukup sebagai buruk sebagai using namespace std. Mungkin karena:

  1. C # tidak memiliki file header. Tidak umum untuk "memasukkan" satu file sumber C # ke yang lain menggunakan pra-prosesor.

  2. stdnamespace hampir datar yaitu hampir semua fungsi perpustakaan standar, jenis dan variabel ada di dalamnya (ada beberapa pengecualian seperti sub-namespace filesystem). Ini berisi jumlah pengidentifikasi yang sangat, sangat tinggi. Menurut pemahaman saya, Systemmengandung jauh lebih sedikit nama, dan sebagai gantinya memiliki lebih banyak sub-ruang nama.

  3. Dalam C #, tidak ada fungsi atau variabel global. Dengan demikian, jumlah pengidentifikasi global biasanya cukup kecil berbeda dengan C ++ yang memang memiliki itu: Lebih jauh, biasanya menggunakan perpustakaan C (sering secara tidak langsung) yang tidak memiliki ruang nama, dan karenanya menempatkan semua nama mereka ke dalam global namespace.

  4. Sejauh yang saya tahu, C # tidak memiliki pencarian berdasarkan argumen. ADL bersamaan dengan penyembunyian nama, kelebihan beban, dll. Dapat menghasilkan kasus di mana beberapa program tidak terpengaruh oleh konflik nama, sementara yang lain terpengaruh secara halus, dan menangkap semua kasus sudut tidak layak dengan pengujian.

Karena perbedaan-perbedaan ini, "menggunakan Sistem;" memiliki kemungkinan konflik nama yang lebih rendah daripada using namespace std.


Juga, namespace "mengimpor" dengan cara tertentu, sebuah konvensi yang berkelanjutan: Jika konvensional untuk mengimpor namespace standar, maka programmer secara konvensional akan mencoba untuk menghindari memilih nama dari namespace itu untuk pengidentifikasi mereka sendiri, yang membantu mengurangi masalah dengan konvensi semacam itu.

Jika impor semacam itu dianggap praktik yang buruk, maka programmer akan cenderung untuk mencoba menghindari konflik dengan ruang nama yang diimpor. Dengan demikian, konvensi cenderung dipolarisasi baik untuk atau melawan praktik, bahkan jika bobot argumen antara pilihan pada awalnya halus.

eerorika
sumber
3
Ini hanya mempertimbangkan kelemahan potensial pembukaan ruang nama. Itu awal, tapi saya pikir kita juga perlu mempertimbangkan keuntungan: dalam kasus C ++, dalam kebanyakan kasus itu menghemat lima karakter ( std::). Dalam C #, ini jauh lebih banyak ( System.memiliki "hanya" 7 karakter, tetapi ruang nama bersarang lainnya memiliki lebih banyak karakter, dan menuliskannya di mana-mana akan membuat kode benar-benar tidak dapat dibaca).
Konrad Rudolph
Bukankah ini masalahnya juga bahwa resolusi overload C # lebih baik daripada yang ada di C ++ dan banyak ambiguitas diambil melalui kesalahan kompiler? (Tidak berarti kritik atas jawaban Anda yang tampaknya berwibawa.)
Batsyeba
3
@KonradRudolph Jika kekurangannya dianggap signifikan, dan jumlah pengetikan sama (dibandingkan dengan jumlah pengetikan std::), bukankah itu gaya yang umum digunakan using Sys = System;sebagai ganti namespace yang mencemari non-alias using?
eerorika
2
@Bathsheba tentang "otoritatif", saya ingin menyangkal bahwa saya tahu sedikit tentang C #, dan jawaban saya didasarkan pada pengetahuan tentang C ++, dan beberapa pencarian google tentang C #. Jadi, saya akan menghargai jika ada yang memeriksa bagian C # :)
eerorika
2
Mengenai bagian ADL: C # memiliki metode ekstensi. Ini desain yang berbeda dari ADL, tetapi mereka berbagi masalah yang sama mengenai konflik penamaan.
Timo
-2

Namun, terlepas dari perbedaan mereka, menggunakan arahan dalam C # dan C ++ melayani tujuan yang sama, yang hanya harus mengetik SomeType sepanjang waktu, daripada Some.Namespace.SomeType (dalam C ++ dengan :: bukannya.) Yang lebih lama. Dan dengan tujuan yang sama, bahaya juga tampak bagi saya: penamaan tabrakan.

Ya, tetapi Anda tidak mengekspor bahaya itu (baca: memaksa orang lain menghadapinya), karena:

Sekarang, saya mengerti bahwa menggunakan arahan dalam C # dan C ++ tidak persis sama. Juga, saya mengerti bahwa salah satu hal paling jahat yang dapat Anda lakukan dengan menggunakan namespace di C ++, yaitu meletakkannya di file header, tidak memiliki padanan dalam C # karena kurangnya konsep file header dan #include.

Jadi ini adalah kategori yang berbeda.

Juga, C ++ tidak "dirancang" untuk dikembangkan dalam IDE seperti halnya C #. C # pada dasarnya selalu ditulis dalam Visual Studio dengan Intellisense dan yang lainnya. Ini dirancang untuk digunakan seperti itu, oleh orang-orang yang membuatnya. Terlepas dari berapa banyak orang menggunakan IDE untuk dikembangkan di C ++, itu tidak dirancang dengan kasus penggunaan itu sebagai masalah besar.

Ruang nama tampaknya jauh lebih "butiran halus" di C # daripada di C ++.

Ya itu juga. using namespace stddan using System.Collection.Generictidak ada bandingannya.

Jadi jangan bandingkan mereka!

Asteroid Dengan Sayap
sumber
2
Ini tidak menjawab kekhawatiran OP, yang secara eksplisit bukan tentang membuka ruang nama di header, tetapi dalam file implementasi .
Konrad Rudolph
2
@KonradRudolph Saran yang harus dihindari using namespace stddalam C ++ kebanyakan tentang file header. Jawabannya adalah ini tidak berlaku dalam C #.
Asteroid Dengan Sayap
8
@AsteroidsWithWings, saran untuk menghindari using namespace stdtentu saja bukan tentang header. Menggunakannya di header berbahaya. Menggunakannya dalam implementasi Anda disarankan.
Tommy Andersen
1
Saran untuk menghindari using namespace ...dalam c ++ adalah tentang menghindari penamaan tabrakan, usingarahan dalam C # memperkenalkan kemungkinan penamaan tabrakan juga, lalu mengapa tidak menghindarinya? Meski ada implementasinya berbeda.
Tommy Andersen
@TommyAndersen, seberapa sulitkah untuk menyelesaikan konflik seperti itu jika itu terjadi? Butuh sedetik. Karena usingdeklarasi C # adalah per file yang mendefinisikan tipe / kelas tunggal dan tipe biasanya berkaitan dengan serangkaian konsep domain aplikasi yang relatif sempit (idealnya, prinsip tanggung jawab tunggal) probabilitas bentrokan namespace tersebut sangat rendah. Tetapi ketika terjadi mudah diperbaiki. Alat pengembangan .NET umum / IDE banyak membantu Anda dengan itu. Pertimbangkan seluruh ekosistem pengembangan yang dirancang untuk membuat Anda lebih produktif dengan menggabungkan yang terbaik dari berbagai kegiatan pengembangan
AKornich