2013-11-09 3 views
13

Я занимаюсь реализацией спецификации C# 7.16.2 «Перевод выражения запроса» в Roslyn. Однако я столкнулся с проблемой в 7.16.2.5 «Выбор предложений».Несоответствие в спецификации C# 7.16.2.5

Он читает

выражение запроса вида

from x in e select v 

переводится на

(e) . Select (x => v) 

исключением случаев, когда v является идентификатором х, перевод просто

(e) 

Например

from c in customers.Where(c => c.City == "London") 
select c 

просто переводится в

customers.Where(c => c.City == "London") 

Мой код не дает результата, соответствующий пример, потому что (как на линии «кроме случаев, когда») я перевожу from x in e select x в (e), а не только e. Таким образом, мой код переводит пример в

(customers.Where(c => c.City == "London")) 

Является примером в спецификации не так, или мне нужно делать обработку признать, необходимы ли вмещающие скобки? Если да, это где-то в спецификации?

Аналогично, 7.16.2.6 (GroupBy положения) говорит

Выражение запроса формы

from x in e group v by k 

переводится в

(e) . GroupBy (x => k , x => v) 

исключением случаев, когда v является идентификатором х , перевод

(e) . GroupBy (x => k) 

Пример

from c in customers 
group c.Name by c.Country 

переводится в

customers. 
GroupBy(c => c.Country, c => c.Name) 

где снова пример результата не хватает скобки, предложенные в спецификации.

+2

Я думаю, что в скобках указано, что 'e' оценивается первым и выбирает, группируя, как применяется позже. В примере используется набор «клиентов», где клиенты такие же, как «(клиенты)», но представьте, что у вас есть оператор +, используемый для конкатенации двух списков - 'from x in a + b' должен быть переведен в' (a + б) .Where'. Я предполагаю, что() является правильным, и пример является только упрощенной версией того же (для этого конкретного случая) – Ondra

+0

@Ondra Да, я понял, что именно поэтому скобки есть (и спасибо за хороший пример того, где он сломается без них!). Меня просто беспокоит, потому что, поскольку примеры в спецификации упрощены, мне интересно, нужно ли мне выяснить, как сделать мою собственную реализацию, выполнить такое же упрощение. – Rawling

+1

@ Rawling Зачем вам это нужно? Код с круглыми скобками всегда будет правильным. – svick

ответ

0

Ваш перевод с дополнительными ( и ) указан неверно. Но если вы хотите, чтобы устранить лишние скобки, вы можете вызвать

.WithAdditionalAnnotations(CodeAnnotations.Simplify) 

на вашем результате SyntaxNode.

+0

Какое влияние это должно иметь? Я попробовал его в результате разбора простого '(Enumerable.Range (1, 5)). Выберите (x => x * x)' и он ничего не делает. Скобки все еще находятся в самом дереве a на выходе, например. 'ToFullString()'. – Rawling

+0

@ Rawling Hmmm. При запуске CodeAction в Visual Studio эффект: a.o. что избыточные скобки удаляются. Если вы используете Rolsyn в своем приложении, я предполагаю, что вам нужно вызвать некоторый метод Roslyn, чтобы сделать фактическое упрощение, но я не знаю, какой именно метод, или даже если он доступен. Это может быть функция Visual Studio. –

+0

Да, мне нужно попробовать. Я нашел * * способ сделать это в коде, но это ужасно: D – Rawling

2

В примере конструкция 'e' является выражением, а конструкция '(e)' представляет собой первичный.То есть в грамматике C# есть производство, которое позволяет использовать «(e)» везде, где ожидается первичное. Существует также производство, которое позволяет использовать первичный объект везде, где ожидается выражение.

В фрагменте кода «from» требуется выражение «e» (в соответствии с грамматикой C#), а в фрагменте «Select()» требуется первичное значение, представленное здесь как «(e)».

Автор примера (возможно, неразумно) выбрал первичные «клиенты», а не выражение, чтобы проиллюстрировать эту точку. Если бы этот пример использовал выражение вместо этого, то в переводе содержались бы круглые скобки. Пример правильный, но пограничный ввод в заблуждение.

В ответ на ваш вопрос вы можете узнать, нужны ли скобки, распознавая, имеете ли вы дело с первичным или выражением. Для первичного они не являются.

Раскрытие информации: моя экспертиза - это технология компилятора, синтаксис C# и Reflection.Emit, но не (пока) Roslyn. Я не мог найти никаких онлайн-документов, поэтому я не могу рассказать вам, как это сделать в Roslyn.

+0

Привет, Дэвид, благодаря этому я нашел раздел «первичные выражения» в спецификации C#, который перечисляет загрузку выражений, которые, я считаю, я может определенно удалить скобки из: D Я не уверен, есть ли в Roslyn «Expression.IsPrimary», который я могу использовать, но я могу определенно работать со списком. – Rawling

Смежные вопросы