Ini adalah pertanyaan yang sangat bagus, karena saya telah melihat sejumlah pengembang C ++ menulis kode C # yang mengerikan.
Sebaiknya jangan menganggap C # sebagai "C ++ dengan sintaks yang lebih bagus". Mereka adalah bahasa berbeda yang memerlukan pendekatan berbeda dalam pemikiran Anda. C ++ memaksa Anda untuk terus berpikir tentang apa yang akan dilakukan CPU dan memori. C # tidak seperti itu. C # khusus dirancang agar Anda tidak memikirkan CPU dan memori dan sebaliknya memikirkan domain bisnis tempat Anda menulis .
Salah satu contoh dari ini yang telah saya lihat adalah bahwa banyak pengembang C ++ akan suka menggunakan untuk loop karena mereka lebih cepat daripada foreach. Ini biasanya merupakan ide yang buruk di C # karena membatasi jenis koleksi yang mungkin diulangi (dan karena itu kegunaan ulang dan fleksibilitas kode).
Saya pikir cara terbaik untuk menyesuaikan dari C ++ ke C # adalah dengan mencoba dan mendekati pengkodean dari perspektif yang berbeda. Pada awalnya ini akan sulit, karena selama bertahun-tahun Anda akan sepenuhnya terbiasa menggunakan utas "apa yang CPU dan memori lakukan" di otak Anda untuk memfilter kode yang Anda tulis. Namun dalam C #, Anda seharusnya memikirkan hubungan antara objek dalam domain bisnis. "Apa yang ingin saya lakukan" sebagai kebalikan dari "apa yang dilakukan komputer".
Jika Anda ingin melakukan sesuatu untuk semua yang ada di daftar objek, alih-alih menulis loop for pada daftar, buat metode yang mengambil IEnumerable<MyObject>
dan menggunakan foreach
loop.
Contoh spesifik Anda:
Mengontrol masa pakai sumber daya yang memerlukan pembersihan deterministik (seperti file). Ini mudah digunakan di tangan tetapi bagaimana menggunakannya dengan benar ketika kepemilikan sumber daya sedang ditransfer [... antara utas]? Dalam C ++ saya hanya akan menggunakan pointer bersama dan membiarkannya mengurus 'pengumpulan sampah' pada waktu yang tepat.
Anda seharusnya tidak pernah melakukan ini di C # (terutama di antara utas). Jika Anda perlu melakukan sesuatu pada suatu file, lakukan di satu tempat pada satu waktu. Tidak apa-apa (dan memang praktik yang baik) untuk menulis kelas pembungkus yang mengelola sumber daya yang tidak dikelola yang melewati antara kelas Anda, tetapi jangan mencoba dan meneruskan File antara utas dan memiliki kelas terpisah menulis / membaca / menutup / membukanya. Jangan berbagi kepemilikan sumber daya yang tidak dikelola. Gunakan Dispose
pola untuk menangani pembersihan.
Perjuangan konstan dengan fungsi-fungsi utama untuk generik tertentu (Saya suka hal-hal seperti spesialisasi template parsial di C ++). Haruskah saya mengabaikan segala upaya untuk melakukan pemrograman generik dalam C #? Mungkin obat generik terbatas pada tujuan dan bukankah C # -ish untuk menggunakannya kecuali untuk domain masalah tertentu?
Generik dalam C # dirancang untuk menjadi generik. Spesialisasi generik harus ditangani oleh kelas turunan. Mengapa harus List<T>
berperilaku berbeda jika itu adalah List<int>
atau List<string>
? Semua operasi pada List<T>
generik sehingga berlaku untuk apa pun List<T>
. Jika Anda ingin mengubah perilaku .Add
metode pada a List<string>
, maka buat kelas turunan MySpecializedStringCollection : List<string>
atau kelas komposisi MySpecializedStringCollection : IList<string>
yang menggunakan generik secara internal tetapi melakukan hal-hal dengan cara yang berbeda. Ini membantu Anda menghindari melanggar Prinsip Pergantian Liskov dan secara tidak sopan meniduri orang lain yang menggunakan kelas Anda.
Fungsionalitas seperti makro. Meskipun umumnya ide yang buruk, untuk beberapa domain masalah tidak ada solusi lain (misalnya evaluasi kondisional dari pernyataan, seperti dengan log yang seharusnya hanya untuk rilis Debug). Tidak memilikinya berarti saya perlu menambahkan lebih banyak (kondisi) {...} boilerplate dan itu masih tidak sama dalam hal memicu efek samping.
Seperti yang orang lain katakan, Anda dapat menggunakan perintah preprocessor untuk melakukan ini. Atribut bahkan lebih baik. Secara umum, atribut adalah cara terbaik untuk menangani hal-hal yang bukan fungsi "inti" untuk sebuah kelas.
Singkatnya, ketika menulis C #, perlu diingat bahwa Anda harus berpikir sepenuhnya tentang domain bisnis dan bukan tentang CPU dan memori. Anda dapat mengoptimalkan nanti jika perlu , tetapi kode Anda harus mencerminkan hubungan antara prinsip-prinsip bisnis yang Anda coba petakan.
C#
untuk menghasilkan kode lain. Anda dapat membacaCSV
atauXML
atau apa yang Anda file sebagai input dan menghasilkanC#
atauSQL
file. Ini bisa lebih kuat daripada menggunakan makro fungsional.