Roslyn 使用 MemberAccessExpressionSyntax 而不是 QualifiedNameSyntax

Roslyn uses MemberAccessExpressionSyntax instead of QualifiedNameSyntax

following code, I'd expect that both references to System.Action type to be represented as a QualifiedNameSyntax but the second one is represented as a MemberAccessExpressionSyntax.

对吗?如果是这样,为什么不能是 QualifiedNameSyntax

class Foo
{
    public void M(object o)
    {
        var t = typeof(System.Action); // 1
        switch(o)
        {
            case System.Action: // 2
                break;
        }
    }
}

我不能肯定地告诉你原因,但这里有一件相关的事情需要考虑:

在法律法规中,我认为你是对的,开关永远不能接受 MemberAccessExpression,因此 QualifiedNameSyntax 足以表示这一点。

但是让我们看一些非法代码,看看会发生什么:

class Foo
{
    public static void M(object o)
    {
        var t = typeof(Foo.M(5)); // 1
        switch(o)
        {
            case Foo.M(5): // 2
                break;
        }
    }
}

首次使用 Foo.M(5) 时出现 4 个错误:

error CS1026: ) expected
error CS1002: ; expected
error CS1513: } expected
error CS0426: The type name 'M' does not exist in the type 'Foo'

第二个只有 1 个:

error CS0426: The type name 'M' does not exist in the type 'Foo'

通过在第二种情况下允许更灵活的语法,错误消息会更好,因为它们可以在语义级别而不是语法级别完成。

由于 switch 表达式接受任何模式作为大小写,因此您更有可能编写无效的内容,因此在这种情况下良好的错误消息更为重要。

通常,您只会在 Roslyn 语法树中获得 QualifiedNameSyntax,其中 只有 合法的东西有限定名称;在那些情况下,我们是 运行 一个只能理解限定名称的受限解析器。我们的其他任何东西都是 运行 我们的通用表达式解析器,它将吐出那里的任何表达式,我们将在绑定期间弄清楚它实际上是什么。因为考虑另一种情况:

SomeEnum e;
switch (e)
{
     case SomeEnum.Blue: Console.WriteLine("Blue!"); return;
}

在那种情况下,SomeEnum.Blue 绝对是对成员的访问。但是在绑定之前我们实际上并不知道“SomeEnum”是什么,所以我们总是使用 MemberAccessExpression。