Это происходит потому, что первые два фрагмента кода (5
и Console.WriteLine
) являются выражениями. Точнее, это соответственно NumericLiteralExpression
и InvocationExpression
.
Последний (throw new Exception()
) является выражением, в данном случае: ThrowStatement
.
Если вы посмотрите на Roslyn SDK, вы заметите, что объект MethodDeclarationSyntax
имеет свойство ExpressionBody
типа ArrowExpressionClauseSyntax
, которое, в свою очередь, имеет свойство типа ExpressionSyntax
. Это должно сделать очевидным, что в элементе с телом выражения принимаются только выражения.
Если вы посмотрите на последний пример кода, вы заметите, что он состоит из ThrowStatementSyntax
, который, в свою очередь, имеет свойство ExpressionSyntax
. В нашем случае мы заполняем его объектом ObjectCreationExpressionSyntax
.
В чем разница между выражением и оператором?
Почему он также не принимает заявления?
Я могу только догадываться, но я предполагаю, что это связано с тем, что это приведет к слишком большому количеству побочных эффектов, чтобы иметь возможность генерировать исключение. Я не верю, что выражение и оператор имеют общего предка в наследовании, поэтому будет много дублирования кода. В конце концов, я предполагаю, что все сводилось к тому, что просто не стоило доставлять хлопот, хотя в некотором смысле это имеет смысл.
Когда вы пишете простое выражение как часть тела метода, которое на самом деле заворачивается в ExpressionStatementSyntax
— да, оба вместе! Это позволяет сгруппировать его вместе с другими операторами в свойстве Body
метода. Под капотом они, должно быть, разворачивают это и извлекают из него выражение. Это, в свою очередь, можно использовать для члена с телом выражения, потому что на этом этапе у вас остается только выражение, а не инструкция.
Однако одно важное замечание здесь заключается в том, что оператор return является... оператором. Точнее, ReturnStatementSyntax
. Должно быть, они обработали это явно и применили магию компилятора, хотя возникает вопрос: почему бы не сделать то же самое для ThrowStatementSyntax
?
Рассмотрим следующий сценарий: внезапно принимается также throw
утверждений. Однако, поскольку член с телом выражения может иметь только выражения в качестве своего тела (да), это означает, что вы должны опустить ключевое слово throw
и вместо этого оставить new Exception()
. Как вы собираетесь отличить намерение оператора return
от утверждения throw
?
Не было бы никакой разницы между вариантами этих двух методов с телом выражения:
public Exception MyMethod()
{
return new Exception();
}
public Exception MyMethod()
{
throw new Exception();
}
И оператор throw
, и оператор return
являются допустимыми окончаниями методов. Однако, когда вы опускаете их, нет ничего, что отличало бы их друг от друга - ergo: вы никогда не будете знать, следует ли возвращать или выбрасывать этот вновь созданный объект исключения.
Что я должен вынести из этого?
Член с телом-выражением в точности соответствует названию: член, содержащий только выражение в своем теле. Это означает, что вы должны знать, что именно представляет собой выражение. То, что это одно «утверждение», не делает его выражением.
person
Jeroen Vannevel
schedule
23.08.2015
NotImplementedException
- person Jeroen Vannevel   schedule 24.08.2015