Ответ 1
Интересные сценарии. Рассмотрим, как компилятор анализирует каждый.
В вашем первом сценарии единственная возможность состоит в том, что x является A и y является B. Все остальное создает ошибку.
В вашем втором сценарии мы могли бы иметь x, A - это B, или x - это B, y равно A. Либо решение работает, мы не имеем оснований, чтобы предпочесть его, поэтому программа неоднозначна.
Теперь рассмотрим ваш третий сценарий. Начнем с предположения, что x равно B. Если x есть B, то y может быть A или B. У нас нет причин предпочитать A или B для y. Поэтому программа, в которой x есть B, неоднозначна. Следовательно, x не может быть B; наше предположение должно быть ошибочным.
Итак, либо x есть A, либо программа ошибочна. Может х быть А? Если это так, то y должно быть B. Мы не выводим ошибку, если x является A, и мы выводим ошибку, если x является B, поэтому x должно быть A.
Из этого можно сделать вывод, что x есть A и y есть B.
Это странно.
Угу. Разрешение перегрузки достаточно сложно в мире без вывода типового типа и лямбда. С ними это действительно довольно сложно.
Я подозреваю, что ваша трудность заключается в том, что кажется лучшим анализом для третьего сценария:
- x - A, y - A не выполняется
- x - это A, y - работа B
- x - это B, y - A works
- x - это B, y - это B работает
- поэтому есть три решения, ни один не лучше, поэтому это неоднозначно.
Это не так, как это работает. Скорее, мы даем все возможные назначения типа самой внешней лямбда и пытаемся добиться успеха или неудачи для каждого.
Если вы сделаете аргумент, что это немного странно, что "порядок имеет значение" - лямбда снаружи в некотором смысле "привилегирована" над лямбдами внутри, ну, конечно, я могу видеть этот аргумент. Это характер алгоритмов обратного отслеживания.
Если у него более одного решения, компиляция не выполняется с ошибкой двусмысленности.
Это все еще так. В первом и третьем сценариях есть одно решение, которое можно вывести без противоречия; во втором - два решения и это двусмысленное.
Есть ли веская причина для текущего поведения?
Да. Мы рассматривали эти правила чрезвычайно тщательно. Как и все проектные решения, был достигнут компромисс.
Это просто вопрос облегчения жизни компилятора?
HA HA HA HA HA HA HA HA HA.
Мне потребовалась большая часть года, чтобы проектировать, уточнять, реализовывать и тестировать всю эту логику, а также много времени и усилий со стороны многих моих коллег. Легко не входит в какую-либо его часть.
Или это скорее недостаток компилятора/спецификации?
Нет.
Цель процесса спецификации заключалась в разработке дизайна, в котором были сделаны разумные выводы, учитывая виды перегрузок, которые мы видели в стандартных библиотеках LINQ. Я думаю, мы достигли этой цели. "Добавление перегрузки никогда не приводит к тому, что двусмысленная программа становится недвусмысленной" не была в какой-то момент целью процесса спецификации.