我正在尝试在 Roslyn 中实现 C# 规范 7.16.2"查询表达式翻译"。但是,我在 7.16.2.5"选择子句"中遇到了问题。
上面写着
表单的查询表达式
from x in e select v
被翻译成
( e ) . Select ( x => v )
除了当 v 是标识符 x 时,翻译只是
( 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(分组子句)说
表单的查询表达式
from x in e group v by k
被翻译成
( e ) . GroupBy ( x => k , x => v )
除非 v 是标识符 x,否则翻译为
( e ) . GroupBy ( x => k )
示例
from c in customers group c.Name by c.Country
被翻译成
customers. GroupBy(c => c.Country, c => c.Name)
其中示例结果再次缺少规范建议的括号。
在示例中,构造 'e' 是一个表达式,构造 '( e )' 表示一个主表达式。也就是说,C# 语法中有一个生产,允许在任何预期主数据库的地方使用"( e )"。还有一个生产允许在任何需要表达式的地方使用主节点。
在"from"代码片段中,需要表达式"e"(根据 C# 语法),在"Select()"片段中需要一个主表达式,此处表示为"( e )"。
该示例的作者(也许是不明智的)选择了主要的"客户"而不是表达来说明这一点。如果示例使用表达式代替,则翻译将包含括号。这个例子是正确的,但具有误导性。
在回答您的问题时,您可以通过识别您正在处理的是主词还是表达式来识别括号是否必要。对于初选来说,他们不是。
披露:我的专长是编译器技术,C#语法和Reflection.Emit,但(还)不是Roslyn。我找不到任何在线文档,所以我无法告诉您如何在 Roslyn 中执行此操作。
带有附加(
和)
的翻译是正确的。但是如果你想消除多余的括号,你可以调用
.WithAdditionalAnnotations(CodeAnnotations.Simplify)
在您生成的SyntaxNode
.