Apa penyebab masalah ini?
Sepertinya bug kompiler bagi saya. Setidaknya, memang begitu. Meskipun ekspresi decimal.TryParse(v, out a)
dan decimal.TryParse(v, out b)
dievaluasi secara dinamis, saya berharap kompilator masih memahami bahwa pada saat mencapai a <= b
, keduanya a
dan b
sudah pasti ditetapkan. Bahkan dengan keanehan yang dapat Anda temukan dalam pengetikan dinamis, saya berharap untuk hanya mengevaluasi a <= b
setelah mengevaluasi kedua TryParse
panggilan tersebut.
Namun, ternyata melalui operator dan konversi yang rumit, sangat mungkin untuk memiliki ekspresi A && B && C
yang mengevaluasi A
dan C
tetapi tidak B
- jika Anda cukup licik. Lihat laporan bug Roslyn untuk contoh cerdik Neal Gafter.
Membuatnya bekerja dengan dynamic
lebih sulit - semantik yang terlibat saat operan dinamis lebih sulit untuk dijelaskan, karena untuk melakukan resolusi kelebihan beban, Anda perlu mengevaluasi operan untuk mengetahui jenis apa yang terlibat, yang dapat menjadi kontra-intuitif. Namun, sekali lagi Neal memberikan contoh yang menunjukkan bahwa kesalahan kompilator diperlukan ... ini bukan bug, ini perbaikan bug . Pujian dalam jumlah besar untuk Neal karena telah membuktikannya.
Apakah mungkin untuk memperbaikinya melalui pengaturan kompiler?
Tidak, tetapi ada alternatif yang menghindari kesalahan tersebut.
Pertama, Anda dapat menghentikannya agar tidak dinamis - jika Anda tahu bahwa Anda hanya akan pernah menggunakan string, maka Anda dapat menggunakan IEnumerable<string>
atau memberikan variabel rentang v
jenis string
(yaitu from string v in array
). Itu akan menjadi pilihan yang saya sukai.
Jika Anda benar - benar perlu menjaganya tetap dinamis, berikan b
nilai sebagai permulaan:
decimal a, b = 0m;
Ini tidak akan merugikan - kami tahu bahwa sebenarnya evaluasi dinamis Anda tidak akan melakukan sesuatu yang gila, jadi Anda tetap akan menetapkan nilai b
sebelum Anda menggunakannya, membuat nilai awal tidak relevan.
Selain itu, tampaknya menambahkan tanda kurung juga berfungsi:
where decimal.TryParse(v, out a) && (decimal.TryParse("15", out b) && a <= b)
Itu mengubah titik di mana berbagai bagian resolusi berlebih dipicu, dan kebetulan membuat kompiler senang.
Ada satu masalah yang masih tersisa - aturan spesifikasi tentang penetapan pasti dengan &&
operator perlu diklarifikasi untuk menyatakan bahwa mereka hanya berlaku ketika &&
operator sedang digunakan dalam implementasi "reguler" dengan dua bool
operan. Saya akan mencoba untuk memastikan ini diperbaiki untuk standar ECMA berikutnya.
b
setelah menetapkannya melaluiout
parameter.