Причина, по которой параметры и переменные лямбды из охватывающей области находятся в одном и том же «пространстве имен» (в смысле свободной привязки имен, а не в смысле языковых возможностей), заключается в том, что лямбды могут закрывать (обращаться) к переменным из объем ограждения. Параметры лямбды должны отличаться от переменных, которые может видеть лямбда:
int x;
Action a = () => { x = 3; };
Ничего страшного, он присваивает 3 внешним x
.
int x;
Action<int> a = x => { x = 3; };
Это не хорошо - на какой x
мы назначаем 3?
В вашем примере единственная разница - это порядок объявления. Это приведет к ошибке
Action a = () => { x = 3; };
int x = 2;
Компилятор скажет, что вы не можете ссылаться на x
до его объявления. Если вы затем заставите лямбду принимать параметр с тем же именем, мы получим примерно ваш пример:
Action<int> a = x => { x = 3; };
int x;
Если бы это сработало, компилятор в основном следовал бы правилу вида: «попробуйте различные возможные интерпретации кода, и в зависимости от того, какой из них не ошибочен, предположите, что это подразумеваемое значение». C # использует немного более безопасный подход и ожидает, что вы будете конкретны и недвусмысленны, а не будете полагаться на такие правила, чтобы «выбрать победителя».