Що спричиняє цю проблему?
Мені здається помилкою компілятора. Принаймні, так і сталося. Хоча decimal.TryParse(v, out a)
і decimal.TryParse(v, out b)
вирази обчислюються динамічно, я очікував , що компілятор до сих пір зрозуміти , що на той час він досягає a <= b
, як a
і b
виразно присвоєної. Навіть з дивними явищами, які ви можете придумати при динамічному наборі тексту, я сподіваюся, що коли-небудь оцінюватиму лише a <= b
після оцінки обох TryParse
дзвінків.
Тим НЕ менше, виявляється, що через оператор і перетворення складного, це цілком можливо , щоб мати вираз , A && B && C
яке наводиться A
і , C
але не B
- якщо ви хитра достатньо. Дивіться звіт про помилки Росліна для геніального прикладу Ніла Гафтера.
Зробити цю роботу dynamic
ще складніше - семантику, яка стосується динамічних операндів, важче описати, оскільки для того, щоб виконати розв’язання перевантаження, потрібно оцінити операнди, щоб з’ясувати, про які типи йдеться, що може бути протиінтуїтивним. Однак знову Ніл придумав приклад, який показує, що потрібна помилка компілятора ... це не помилка, це виправлення помилки . Величезна кількість похвали Нілу за те, що він це довів.
Чи можна це виправити за допомогою налаштувань компілятора?
Ні, але є альтернативи, які дозволяють уникнути помилки.
По-перше, ви можете зупинити його динамічність - якщо ви знаєте, що коли-небудь будете використовувати лише рядки, тоді ви можете використовувати IEnumerable<string>
або надати змінної діапазону v
тип string
(тобто from string v in array
). Це був би мій найкращий варіант.
Якщо вам дійсно потрібно зберегти його динамічність, просто вкажіть b
значення для початку:
decimal a, b = 0m;
Це не зашкодить - ми знаємо, що насправді ваше динамічне оцінювання не зробить нічого шаленого, тому ви все одно присвоїте значення, b
перш ніж використовувати його, роблячи початкове значення неактуальним.
Крім того, здається, що додавання дужок теж працює:
where decimal.TryParse(v, out a) && (decimal.TryParse("15", out b) && a <= b)
Це змінює точку, в якій запускаються різні деталі дозволу на перевантаження, і це робить компілятор щасливим.
Залишилось одне питання - правила специфікації щодо визначеного присвоєння &&
оператору потрібно уточнити, щоб зазначити, що вони застосовуються лише тоді, коли &&
оператор використовується у його "регулярній" реалізації з двома bool
операндами. Я спробую переконатися, що це виправлено для наступного стандарту ECMA.
b
після присвоєння його за допомогоюout
параметра.