想象一下根命名空间级别的类型(可能在默认global
空间中,或者可能是一个extern alias
)。
使用别名前缀时,似乎无法通过 引用此类型。nameof()
它适用于typeof
, 和 viausing
别名(尽管nameof
在using
别名上产生别名,而不是类型名)。带有 CS8083 的编译器对象,“别名限定名称不是表达式。”
但是:这是有原因的吗?这是为了防止一些模糊的问题场景吗?或满足一些规格要求?或者它可能是一个编译器错误?我也很满意地注意到我们通常不应该在命名空间根中声明类型——CA1050
这是非常正确的;但这不是重点:)
完整示例如下;请注意,在此示例中使用两个项目进行using
别名检查,但为简单起见,所有涉及的内容C
都可以忽略以进行简单调查。
extern alias foo;
using System;
using X = global::A;
using Y = global::FunWithNamespaces.B;
using Z = foo::C;
public class A { }
namespace FunWithNamespaces
{
public class B { }
public class Program
{
static void Main()
{
// oddness is on the lines marked ## CS8083
// relative-qualified using typeof
Console.WriteLine(typeof(X).Name); // A, expected
Console.WriteLine(typeof(Y).Name); // B, expected
Console.WriteLine(typeof(Z).Name); // C, expected
Console.WriteLine(typeof(A).Name); // A
Console.WriteLine(typeof(B).Name); // B
// note: can't talk about C without using an alias qualifier or a using-alias
Console.WriteLine(typeof(Console).Name); // Console
// relative-qualified things using nameof
Console.WriteLine(nameof(X)); // X; I'm on the fence about X vs A, but... whatever
Console.WriteLine(nameof(Y)); // Y; I'm on the fence about Y vs B, but... whatever
Console.WriteLine(nameof(Z)); // Z; I'm on the fence about Z vs C, but... whatever
Console.WriteLine(nameof(A)); // A
Console.WriteLine(nameof(B)); // B
// note: can't talk about C without using an alias qualifier or a using-alias
Console.WriteLine(nameof(Console)); // Console
// alias-qualified things using typeof
Console.WriteLine(typeof(global::A).Name); // A
Console.WriteLine(typeof(global::FunWithNamespaces.B).Name); // B
Console.WriteLine(typeof(foo::C).Name); // C
Console.WriteLine(typeof(global::System.Console).Name); // Console
// alias-qualified things using nameof
// ??? Console.WriteLine(nameof(global::A)); // ## CS8083 An alias-qualified name is not an expression
Console.WriteLine(nameof(global::FunWithNamespaces.B)); // B
// ??? Console.WriteLine(nameof(foo::C)); // ## CS8083 An alias-qualified name is not an expression
Console.WriteLine(nameof(global::System.Console)); // Console
}
}
}
whereC
在单独的程序集中定义并使用指定为 的别名引用foo
,并且很简单:
public class C { }
编辑:就规范而言,这归结为https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/language-specification/expressions#nameof-expressions,其中 anameof_expression
必须是simple_name
(它不是)或named_entity_target '.' identifier type_argument_list?
- 所以:对于所有不是简单名称的情况,必须有.something
- 但我想这里的根本问题是为什么必须有 a .something
, 而其他一些允许的结构global::Foo
?例如:
nameof_expression
: 'nameof' '(' named_entity ')'
;
named_entity
: simple_name
| named_entity_target '.' identifier type_argument_list?
| qualified_alias_member type_argument_list?
;
named_entity_target
: 'this'
| 'base'
| named_entity
| predefined_type
| qualified_alias_member
;