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 adan bsudah pasti ditetapkan. Bahkan dengan keanehan yang dapat Anda temukan dalam pengetikan dinamis, saya berharap untuk hanya mengevaluasi a <= bsetelah mengevaluasi kedua TryParsepanggilan tersebut.
Namun, ternyata melalui operator dan konversi yang rumit, sangat mungkin untuk memiliki ekspresi A && B && Cyang mengevaluasi Adan Ctetapi tidak B- jika Anda cukup licik. Lihat laporan bug Roslyn untuk contoh cerdik Neal Gafter.
Membuatnya bekerja dengan dynamiclebih 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 vjenis string(yaitu from string v in array). Itu akan menjadi pilihan yang saya sukai.
Jika Anda benar - benar perlu menjaganya tetap dinamis, berikan bnilai 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 bsebelum 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 booloperan. Saya akan mencoba untuk memastikan ini diperbaiki untuk standar ECMA berikutnya.
bsetelah menetapkannya melaluioutparameter.