Operator null-penggabungan dalam c # memungkinkan Anda untuk mempersingkat kode
if (_mywidget == null)
return new Widget();
else
return _mywidget;
Ke:
return _mywidget ?? new Widget();
Saya terus menemukan bahwa operator yang berguna yang ingin saya miliki di C # akan menjadi salah satu yang memungkinkan Anda untuk mengembalikan properti suatu objek, atau nilai lain jika objek tersebut nol. Jadi saya ingin mengganti
if (_mywidget == null)
return 5;
else
return _mywidget.Length;
Dengan:
return _mywidget.Length ??! 5;
Saya tidak dapat berhenti berpikir bahwa pasti ada alasan bagi operator ini untuk tidak ada. Apakah ini bau kode? Apakah ada cara yang lebih baik untuk menulis ini? (Saya mengetahui pola objek nol tetapi tampaknya berlebihan untuk menggunakannya untuk mengganti keempat baris kode ini.)
c#
code-smell
null
Ben Fulton
sumber
sumber
??!
adalah operator di C ++. :-)Jawaban:
Saya sangat menginginkan fitur bahasa C # yang memungkinkan saya melakukan x.Prop.SomeOtherProp.ThirdProp dengan aman tanpa harus memeriksa setiap null. Dalam satu basis kode di mana saya harus sering melakukan "deep property traversals", saya menulis metode ekstensi bernama Navigate yang menelan NullReferenceExceptions dan sebagai gantinya mengembalikan nilai default. Jadi saya bisa melakukan sesuatu seperti ini:
Kelemahan dari ini adalah bahwa ia memiliki bau kode yang berbeda: menelan pengecualian. Jika Anda ingin melakukan sesuatu seperti "benar" ini, Anda bisa menggunakan lamdba sebagai ekspresi, dan memodifikasi ekspresi dengan cepat untuk menambahkan cek nol di sekitar setiap accessor properti. Saya memilih "cepat dan kotor" dan tidak menerapkannya dengan cara "lebih baik" ini. Tetapi mungkin ketika saya memiliki beberapa siklus pemikiran cadangan saya akan mengunjungi kembali ini dan mempostingnya di suatu tempat.
Untuk menjawab pertanyaan Anda secara lebih langsung, saya menduga alasan ini bukan fitur adalah karena biaya penerapan fitur melebihi manfaat dari memiliki fitur tersebut. Tim C # harus memilih dan memilih fitur mana yang menjadi fokus, dan yang ini belum melayang ke atas. Kurasa aku tidak punya info orang dalam.
sumber
Saya yakin Anda bisa melakukan ini dengan C # 6 cukup sederhana sekarang:
Perhatikan operator kondisi nol
?.
di sebelah kiri._mywidget?.Length
mengembalikan nol jika_mywidget
nol.Operator ternary sederhana mungkin lebih mudah dibaca, seperti yang disarankan orang lain.
sumber
Ini benar-benar hanya spekulasi mengapa mereka tidak melakukannya. Lagipula, saya tidak percaya ?? berada di versi C # pertama.
Bagaimanapun, saya hanya akan menggunakan operator kondisional dan menyebutnya sehari:
Itu ?? hanyalah jalan pintas ke operator bersyarat.
sumber
5
jawabannya jika tidak ada. Anda harus melihat desain Anda sebelum mulai meminta operator khusus.Itu terlihat seperti operator ternary:
sumber
Secara pribadi, saya pikir ini mudah dibaca. Pada contoh pertama,
??
terjemahannya cukup baik sebagai "Apakah Anda di sana ?? Tidak, mari kita lakukan ini".Dalam contoh kedua,
??!
jelas WTF dan tidak ada artinya bagi programmer .... objek tidak ada, jadi saya tidak bisa mendapatkan di properti jadi saya akan kembali 5. Apa artinya itu? Apa itu 5? Bagaimana kita sampai pada kesimpulan bahwa 5 adalah nilai yang baik?Singkatnya, contoh pertama masuk akal ... tidak ada di sana, baru itu. Yang kedua, terbuka untuk diperdebatkan.
sumber
(foo() != ERROR)??!??! cerr << "Error occurred" << endl;
)5
. Saya benar-benar berpikir ada lebih banyak masalah yang harus Anda lakukan seperti ini, sedangkan dalam contoh pertama Anda, kebutuhannya cukup jelas, terutama dalam hal-hal seperti manajer cache.Saya pikir orang terlalu terjebak dalam "5" yang Anda kembalikan ... mungkin 0 akan lebih baik :)
Lagi pula, saya pikir masalahnya adalah bahwa
??!
sebenarnya bukan operator mandiri. Pertimbangkan apa artinya ini:Dalam hal itu, tidak masuk akal: hanya masuk akal jika operan kiri adalah pengakses properti. Atau bagaimana dengan ini:
Ada accessor properti di sana, tapi aku masih tidak berpikir itu masuk akal (jika
myWidget
adalahnull
, apakah itu berarti kita tidak menyebutFoo()
sama sekali?), Atau ini hanya kesalahan?Saya pikir masalahnya adalah itu tidak cocok secara alami dalam bahasa seperti
??
halnya.sumber
Seseorang telah menciptakan kelas utilitas yang akan melakukan ini untuk Anda. Tetapi saya tidak dapat menemukannya. Apa yang saya temukan adalah sesuatu yang serupa di Forum MSDN (lihat jawaban kedua).
Dengan sedikit kerja, Anda dapat memperluasnya untuk mengevaluasi panggilan metode dan ekspresi lain yang tidak didukung sampel. Anda juga dapat memperluasnya untuk menerima nilai default.
sumber
Saya mengerti dari mana Anda berasal. Sepertinya semua orang dibungkus kapak dengan contoh yang Anda berikan. Sementara saya setuju bahwa angka ajaib adalah ide yang buruk, akan ada gunanya untuk setara dengan operator koallescing nol untuk properti tertentu.
Misalnya, Anda memiliki objek yang terikat pada peta, dan Anda ingin objek berada pada ketinggian yang sesuai. Peta DTED dapat memiliki lubang di data mereka sehingga dimungkinkan untuk memiliki nilai nol, serta nilai dalam kisaran sekitar -100 hingga ~ 8900 meter. Anda mungkin menginginkan sesuatu seperti:
Operator pengelompokan nol dalam kasus ini akan mengisi ketinggian standar jika Koordinat belum ditetapkan, atau objek Koordinat tidak dapat memuat data DTED untuk lokasi itu.
Saya melihat ini sebagai sangat berharga, tetapi spekulasi saya mengapa itu tidak dilakukan terbatas pada kompiler kompleksitas. Mungkin ada beberapa kasus di mana perilaku tidak akan dapat diprediksi.
sumber
Ketika tidak berurusan dengan sangat bersarang saya telah menggunakan ini (sebelum operator penggabungan nol diperkenalkan di C # 6). Bagi saya itu cukup jelas, tapi mungkin itu karena saya sudah terbiasa, orang lain mungkin merasa membingungkan.
Tentu saja, ini tidak selalu berlaku, karena kadang-kadang properti yang Anda butuhkan tidak dapat diatur secara langsung, atau ketika konstruksi objek itu sendiri mahal, di antara alasan lainnya.
Alternatif lain adalah dengan menggunakan pola NullObject . Anda mendefinisikan satu instance statis kelas dengan nilai default yang masuk akal, dan menggunakannya sebagai gantinya.
sumber
Angka ajaib biasanya bau. Jika angka 5 adalah angka arbitrer, maka lebih baik untuk mengejanya sehingga didokumentasikan dengan lebih jelas. Pengecualian dalam pendapat saya adalah jika Anda memiliki koleksi nilai yang bertindak sebagai nilai default dalam konteks tertentu.
Jika Anda memiliki satu set nilai default untuk objek, Anda bisa mensubklasifikasikannya untuk membuat instance singleton default.
Sesuatu seperti: return (myobj ?? default_obj). Panjang
sumber
Properti length biasanya adalah tipe nilai sehingga tidak bisa null, jadi operator null-coalescing tidak masuk akal di sini.
Tetapi Anda dapat melakukannya dengan properti yang merupakan tipe referensi, misalnya:
var window = App.Current.MainWindow ?? new Window();
sumber
Saya telah melihat seseorang dengan ide serupa sebelumnya tetapi sebagian besar waktu Anda ingin juga menetapkan nilai baru ke bidang nol, sesuatu seperti:
jadi idenya adalah untuk menggabungkan
??
dan=
tugas menjadi:Saya pikir ini lebih masuk akal daripada menggunakan tanda seru.
Ide ini bukan milikku tapi aku sangat menyukainya :)
sumber
return _obj ?? new Class();
tidak perlu untuk di??=
sini.