Следующий код неверен (см. Его на ideone ):
public class Test
{
public static void Main()
{
int j = 5;
(j++); // if we remove the "(" and ")" then this compiles fine.
}
}
Ошибка CS0201: в качестве оператора могут использоваться только выражения присваивания, вызова, приращения, уменьшения, ожидания и новых объектов
- Почему код компилируется, когда мы удаляем скобки?
- Почему он не компилируется с круглыми скобками?
- Почему C # был разработан таким образом?
c#
syntax
expression
language-design
parentheses
user10607
источник
источник
Ответы:
Я сделаю все возможное.
Как отмечали другие ответы, здесь происходит то, что компилятор обнаруживает, что выражение используется в качестве оператора . Во многих языках - C, JavaScript и многих других - совершенно законно использовать выражение в качестве выражения.
2 + 2;
является законным на этих языках, хотя это утверждение не имеет никакого эффекта. Некоторые выражения полезны только для их значений, некоторые выражения полезны только для их побочных эффектов (таких как вызов метода возврата void), а некоторые выражения, к сожалению, полезны для обоих. (Как приращение.)Дело в том, что утверждения, которые состоят только из выражений, почти наверняка являются ошибками, если только эти выражения обычно не считаются более полезными для их побочных эффектов, чем их значения . Разработчики C # хотели найти золотую середину, позволяя выражениям, которые обычно считались побочными, не допускать выражений, которые обычно считаются полезными для их значений. Множество выражений, которые они идентифицировали в C # 1.0, были приращениями, декрементами, вызовами методов, присваиваниями и, что довольно противоречиво, вызовами конструктора.
В стороне: обычно думают, что конструкция объекта используется как значение, которое он производит, а не как побочный эффект конструкции; по моему мнению,
new Foo();
допуск - это немного неудача. В частности, я видел этот шаблон в реальном коде, который вызвал дефект безопасности:Может быть удивительно трудно обнаружить этот дефект, если код сложен.
Поэтому компилятор работает для обнаружения всех операторов, которые состоят из выражений, которых нет в этом списке. В частности, выражения в скобках идентифицируются как просто выражения в скобках. Их нет в списке «разрешено в качестве выражений операторов», поэтому они запрещены.
Все это служит принципу разработки языка C #. Если вы печатали,
(x++);
вы, вероятно, делали что-то не так . Это, вероятно, опечаткаM(x++);
или просто вещь. Помните, что отношение команды компилятора C # не « можем ли мы найти какой-то способ заставить эту работу? » Отношение команды C # - « если правдоподобный код выглядит как вероятная ошибка, давайте сообщим разработчику ». Разработчикам C # нравится такое отношение.Теперь, все , что сказал, есть на самом деле несколько странных случаев , когда C # спецификация делает предполагающие или состояние напрямую , что круглые скобки запрещены , но C # компилятор позволяет им в любом случае. Почти во всех этих случаях незначительное несоответствие между указанным поведением и разрешенным поведением совершенно безвредно, поэтому авторы компилятора никогда не исправляли эти небольшие ошибки. Вы можете прочитать о них здесь:
Есть ли разница между return myVar и return (myVar)?
источник
... ? ... : ...
, когда исправление будет использоватьсяif
/else
вместо.)contineu;
.try { new Foo(null); } catch (ArgumentNullException)...
но очевидно, что эти ситуации по определению не являются рабочим кодом. Представляется разумным, что такой код может быть написан для присвоения фиктивной переменной.В спецификации языка C #
Помещение скобок в оператор создает новое так называемое выражение в скобках. Из спецификации:
Поскольку выражения в скобках не указаны в качестве допустимого выражения выражения, это не является допустимым выражением согласно спецификации. Почему дизайнеры решили сделать это таким образом, можно только догадываться, но моя ставка заключается в том, что круглые скобки не приносят никакой пользы, если все утверждение содержится в круглых скобках:
stmt
и(stmt)
они точно такие же.источник
OP
ничего не спрашивает о дизайне языка. Он просто хочет знать, почему это ошибка. Ответ: потому что это недопустимое утверждение .поскольку квадратные скобки
i++
создают / определяют выражение ... как говорится в сообщении об ошибке ... простое выражение не может быть использовано в качестве выражения.почему язык был разработан таким образом? для предотвращения ошибок, имеющих вводящие в заблуждение выражения в виде операторов, которые не вызывают побочных эффектов, таких как наличие кода
вторая строка не имеет никакого эффекта (но вы, возможно, не заметили). Но вместо того, чтобы компилятор удалял его (потому что код не нужен) .it явно просит вас удалить его (чтобы вы знали об ошибке) или ИЛИ исправить это, если вы забыли что-то напечатать.
редактировать :
чтобы сделать часть о bracked более понятной ... скобки в c # (помимо других применений, таких как приведение типов и вызов функций), используются для группировки выражений и возврата одного выражения (make из подвыражений).
на этом уровне кода разрешены только позиции .. так
но с помощью пробела вы превращаете его в выражение
и это
недопустимо, потому что компилятор не может убедиться, что выражение является побочным эффектом (не без возникновения проблемы остановки).
источник
j
переменной, верно?j++;
является действительным утверждением, но, используя квадратные скобки, вы говоритеlet me take this stement and turn it into an expression
... и выражения недействительны на тот момент кода