Mana yang lebih baik untuk digunakan, dan mengapa, pada proyek besar:
#if DEBUG
public void SetPrivateValue(int value)
{ ... }
#endif
atau
[System.Diagnostics.Conditional("DEBUG")]
public void SetPrivateValue(int value)
{ ... }
c#
debugging
preprocessor
debug-symbols
Lucas B
sumber
sumber
Jawaban:
Ini benar-benar tergantung pada apa yang Anda tuju:
#if DEBUG
: Kode di sini bahkan tidak akan mencapai IL pada rilis.[Conditional("DEBUG")]
: Kode ini akan mencapai IL, namun panggilan ke metode ini akan dihilangkan kecuali DEBUG diatur saat pemanggil dikompilasi.Secara pribadi saya menggunakan keduanya tergantung pada situasi:
Contoh Bersyarat ("DEBUG"): Saya menggunakan ini sehingga saya tidak harus kembali dan mengedit kode saya nanti selama rilis, tetapi selama debugging saya ingin memastikan saya tidak membuat kesalahan ketik. Fungsi ini memeriksa apakah saya mengetikkan nama properti dengan benar ketika mencoba menggunakannya dalam hal-hal INotifyPropertyChanged saya.
Anda benar-benar tidak ingin membuat fungsi menggunakan
#if DEBUG
kecuali Anda bersedia untuk membungkus setiap panggilan ke fungsi itu dengan yang sama#if DEBUG
:melawan:
#Jika DEBUG contoh: Saya menggunakan ini ketika mencoba mengatur binding yang berbeda untuk komunikasi WCF.
Dalam contoh pertama, semua kode ada, tetapi hanya diabaikan kecuali DEBUG aktif. Dalam contoh kedua, const ENDPOINT diatur ke "Localhost" atau "BasicHttpBinding" tergantung pada apakah DEBUG diatur atau tidak.
Pembaruan: Saya memperbarui jawaban ini untuk memperjelas poin penting dan rumit. Jika Anda memilih untuk menggunakan
ConditionalAttribute
, ingatlah bahwa panggilan dihilangkan selama kompilasi, dan bukan runtime . Itu adalah:MyLibrary.dll
Ketika perpustakaan dikompilasi dengan mode rilis (yaitu tidak ada simbol DEBUG), itu akan selamanya memiliki panggilan
B()
dari dalamA()
dihilangkan, bahkan jika panggilan keA()
dimasukkan karena DEBUG didefinisikan dalam majelis panggilan.sumber
Yah, perlu dicatat bahwa itu tidak berarti sama sekali.
Jika simbol DEBUG tidak didefinisikan, maka dalam kasus pertama
SetPrivateValue
itu sendiri tidak akan dipanggil ... sedangkan dalam kasus kedua itu akan ada, tetapi setiap penelepon yang dikompilasi tanpa simbol DEBUG akan membuat panggilan tersebut dihilangkan.Jika kode dan semua peneleponnya berada dalam rakitan yang sama perbedaan ini kurang penting - tetapi itu berarti bahwa dalam kasus pertama Anda juga perlu memiliki
#if DEBUG
sekitar kode panggilan juga.Secara pribadi saya akan merekomendasikan pendekatan kedua - tetapi Anda harus menjaga perbedaan di antara mereka jelas di kepala Anda.
sumber
Saya yakin banyak yang akan tidak setuju dengan saya, tetapi setelah menghabiskan waktu sebagai tukang bangunan terus-menerus mendengar "Tapi itu bekerja pada mesin saya!", Saya mengambil pendirian bahwa Anda sebaiknya tidak pernah menggunakan keduanya. Jika Anda benar-benar membutuhkan sesuatu untuk pengujian dan debugging, cari cara untuk membuat testabilitas itu terpisah dari kode produksi yang sebenarnya.
Abstraksi skenario dengan mengejek dalam unit test, buat satu versi dari hal-hal untuk satu skenario yang ingin Anda uji, tetapi jangan masukkan tes untuk debug ke dalam kode untuk binari yang Anda uji dan tulis untuk rilis produksi. Tes debug ini hanya menyembunyikan kemungkinan bug dari devs sehingga tidak ditemukan hingga nanti dalam proses.
sumber
#if debug
atau konstruksi serupa dalam kode Anda?#if DEBUG
sehingga kita tidak secara tidak sengaja melakukan spam kepada orang lain saat menguji sistem yang harus mengirimkan email sebagai bagian dari proses. Kadang-kadang ini adalah alat yang tepat untuk pekerjaan itu :)Yang ini bisa bermanfaat juga:
sumber
Debugger.IsAttached
harus dipanggil pada saat runtime bahkan dalam rilis rilis.Dengan contoh pertama,
SetPrivateValue
tidak akan ada di build jikaDEBUG
tidak ditentukan, dengan contoh kedua, panggilan keSetPrivateValue
tidak akan ada di build jikaDEBUG
tidak ditentukan.Dengan contoh pertama, Anda juga harus membungkus semua panggilan
SetPrivateValue
dengan#if DEBUG
.Dengan contoh kedua, panggilan ke
SetPrivateValue
akan dihilangkan, tetapi perlu diketahui bahwaSetPrivateValue
itu sendiri masih akan dikompilasi. Ini berguna jika Anda sedang membangun perpustakaan, jadi aplikasi yang mereferensikan perpustakaan Anda masih dapat menggunakan fungsi Anda (jika kondisinya terpenuhi).Jika Anda ingin menghilangkan panggilan dan menghemat ruang callee, Anda bisa menggunakan kombinasi kedua teknik ini:
sumber
#if DEBUG
sekitarConditional("DEBUG")
tidak menghapus panggilan ke fungsi itu, itu hanya menghapus fungsi dari IL alltogether, jadi Anda masih memiliki panggilan ke fungsi yang tidak ada (kesalahan kompilasi).Mari kita anggap kode Anda juga memiliki
#else
pernyataan yang mendefinisikan fungsi rintisan nol, membahas salah satu poin Jon Skeet. Ada perbedaan penting kedua di antara keduanya.Misalkan fungsi
#if DEBUG
atauConditional
ada dalam DLL yang dirujuk oleh proyek utama Anda yang dapat dieksekusi. Dengan menggunakan#if
, evaluasi kondisional akan dilakukan sehubungan dengan pengaturan kompilasi perpustakaan. MenggunakanConditional
atribut, evaluasi kondisi akan dilakukan sehubungan dengan pengaturan kompilasi dari penyerang.sumber
Saya memiliki ekstensi SOAP WebService untuk mencatat lalu lintas jaringan menggunakan kustom
[TraceExtension]
. Saya menggunakan ini hanya untuk membangun Debug dan menghilangkan dari rilis membangun. Gunakan#if DEBUG
untuk membungkus[TraceExtension]
atribut sehingga menghapusnya dari rilis Rilis .sumber
Biasanya Anda akan membutuhkannya di Program.cs di mana Anda ingin memutuskan untuk menjalankan Debug pada kode Non-Debug dan itu terlalu banyak di Windows Services. Jadi saya membuat isdebugMode bidang readonly dan mengatur nilainya dalam konstruktor statis seperti yang ditunjukkan di bawah ini.
sumber