Игнорирование скобок

Еще один забавный вопрос на StackOverflow: существует ли в C# разница между “return something;” и “return (something);”?

Практически разницы нет.

Теоретически разница может быть. Существует три интересных замечания в спецификации языка C#, из-за которых могут возникнуть проблемы.

Первый пример: преобразование анонимных функций к делегатам или деревьям выражений (expression tree). Рассмотрим следующий код:

Func<int> F1() { return ()=>1; }
Func<int> F2() { return (()=>1); }

Выражение F1 совершенно корректное. А как насчет F2? Технически – нет. В разделе 6.5 спецификации сказано, что существует преобразование лямбда-выражения к делегату совместимого типа. А является ли это лямбда-выражением? Нет, это выражение в скобках, которое содержит лямбда-выражение.

В этом случае компилятор немного нарушает спецификацию и отбрасывает скобки за вас.

Второй пример:

int M() { return 1; }
Func<int> F3() { return M; }
Func<int> F4() { return (M); }

Выражение F3 – корректное. А F4? Нет. В разделе 7.5.3 сказано, что выражение в скобках не должно содержать группу методов (method group). В этом случае ради вашего удобства мы (нечаянно!) нарушаем спецификацию и позволяем это преобразование.

Третий пример:

enum E { None }
E F5() { return 0; }
E F6() { return (0); }

Выражение F5 – корректное. А F6? Нет. В спецификации сказано о том, что существует преобразования из литерала 0 к любому перечислимому типу. "(0)" – это не литерал 0, это открывающая круглая скобка, за которой следует литерал 0, за которой следует закрывающая скобка. В этом случае мы нарушаем спецификацию; на самом деле в этом случае мы позволяем преобразование не только из литерала 0, а из любого константного выражения, равного нулю.

Так что, мы всегда позволяем использовать круглые скобки, хотя технически это и не корректно.

Оригинал статьи