Dengan analogi, C # pada dasarnya seperti seperangkat alat mekanik di mana seseorang telah membaca bahwa Anda biasanya harus menghindari tang dan kunci pas yang dapat disetel, jadi itu tidak termasuk kunci pas yang bisa disetel sama sekali, dan tang dikunci dalam laci khusus bertanda "tidak aman" , dan hanya dapat digunakan dengan persetujuan dari penyelia, setelah menandatangani penafian yang membebaskan majikan Anda dari segala tanggung jawab atas kesehatan Anda.
C ++, sebagai perbandingan, tidak hanya mencakup kunci pas dan tang yang dapat disesuaikan, tetapi beberapa alat tujuan khusus yang agak aneh yang tujuannya tidak segera terlihat, dan jika Anda tidak tahu cara yang tepat untuk memegangnya, mereka mungkin dengan mudah memotong Anda jempol (tapi begitu Anda mengerti cara menggunakannya, dapat melakukan hal-hal yang pada dasarnya tidak mungkin dengan alat dasar di C # toolbox). Selain itu, ia memiliki mesin bubut, mesin penggilingan, penggiling permukaan, gergaji pita logam, dll., Untuk memungkinkan Anda merancang dan membuat alat yang sama sekali baru setiap kali Anda merasa perlu (tapi ya, alat-alat ahli mesin itu dapat dan akan menyebabkan cedera serius jika Anda tidak tahu apa yang Anda lakukan dengan mereka - atau bahkan jika Anda hanya ceroboh).
Itu mencerminkan perbedaan mendasar dalam filosofi: C ++ mencoba memberi Anda semua alat yang mungkin Anda butuhkan untuk setiap desain yang Anda inginkan. Hampir tidak ada upaya untuk mengendalikan bagaimana Anda menggunakan alat-alat itu, sehingga juga mudah untuk menggunakannya untuk menghasilkan desain yang hanya berfungsi dengan baik dalam situasi yang jarang, serta desain yang mungkin hanya ide yang buruk dan tidak ada yang tahu situasi di mana mereka cenderung bekerja dengan baik. Secara khusus, banyak hal ini dilakukan dengan memisahkan keputusan desain - bahkan yang dalam praktiknya hampir selalu digabungkan. Akibatnya, ada perbedaan besar antara hanya menulis C ++, dan menulis C ++ dengan baik. Untuk menulis C ++ dengan baik, Anda perlu tahu banyak idiom dan aturan praktis (termasuk aturan praktis tentang seberapa serius untuk mempertimbangkan kembali sebelum melanggar aturan praktis lainnya). Hasil dari, C ++ lebih berorientasi pada kemudahan penggunaan (oleh para ahli) daripada kemudahan belajar. Ada juga (terlalu banyak) keadaan di mana itu tidak terlalu mudah digunakan.
C # melakukan lebih banyak upaya untuk memaksa (atau paling tidak sangat menyarankan) apa yang dianggap oleh para perancang bahasa sebagai praktik desain yang baik. Cukup banyak hal yang dipisahkan dalam C ++ (tetapi biasanya berjalan bersama dalam praktek) secara langsung digabungkan dalam C #. Itu memang memungkinkan untuk kode "tidak aman" untuk mendorong batas sedikit, tapi jujur, tidak banyak.
Hasilnya adalah bahwa di satu sisi ada beberapa desain yang dapat diekspresikan secara langsung di C ++ yang secara substansial clumsier untuk diekspresikan dalam C #. Di sisi lain, itu adalah seluruh banyak lebih mudah untuk belajar C #, dan kemungkinan menghasilkan desain yang benar-benar mengerikan yang tidak akan bekerja untuk situasi Anda (atau mungkin lainnya) yang drastis berkurang. Dalam banyak (mungkin bahkan sebagian besar) kasus, Anda bisa mendapatkan desain yang solid dan bisa diterapkan hanya dengan "mengikuti arus", begitulah. Atau, sebagai salah satu teman saya (setidaknya saya suka menganggapnya sebagai teman - tidak yakin apakah dia benar-benar setuju) suka mengatakannya, C # membuatnya mudah untuk jatuh ke dalam jurang kesuksesan.
Jadi melihat lebih spesifik pada pertanyaan tentang bagaimana class
dan struct
mendapatkan bagaimana mereka berada dalam dua bahasa: objek yang dibuat dalam hierarki warisan di mana Anda dapat menggunakan objek dari kelas turunan dengan kedok kelas dasar / antarmuka, Anda cukup banyak terjebak dengan fakta bahwa Anda biasanya perlu melakukannya melalui semacam pointer atau referensi - pada tingkat yang konkret, yang terjadi adalah bahwa objek dari kelas turunannya mengandung sesuatu memori yang dapat diperlakukan sebagai turunan dari kelas dasar / antarmuka, dan objek yang diturunkan dimanipulasi melalui alamat bagian memori itu.
Dalam C ++, terserah kepada programmer untuk melakukannya dengan benar - ketika dia menggunakan warisan, terserah padanya untuk memastikan bahwa (misalnya) fungsi yang bekerja dengan kelas polimorfik dalam suatu hierarki melakukannya melalui pointer atau referensi ke basis kelas.
Dalam C #, apa yang secara fundamental pemisahan yang sama antara jenis jauh lebih eksplisit, dan ditegakkan oleh bahasa itu sendiri. Programmer tidak perlu mengambil langkah apa pun untuk melewati instance kelas dengan referensi, karena itu akan terjadi secara default.
struct
s tidak selalu disimpan di tumpukan; pertimbangkan objek denganstruct
bidang. Selain itu, seperti Mason Wheeler menyebutkan masalah mengiris mungkin adalah alasan terbesar.