班级名称中有加号 "+" 的含义是什么?

19

类名:MyAssembly.MyClass+MyOtherClass

问题显然出在使用加号+作为分隔符,而不是传统的点号。需要查找官方文档以确定是否存在其他的分隔符及其功能。


你为什么需要了解这个?你想通过这个知识实现什么目标? - John Saunders
2个回答

27

这就是嵌套类型的表现方式。例如:

namespace Foo
{
    class Outer
    {
        class Nested {}
    }
}

在编译代码中将创建一个名称为Foo.Outer+Nested的类型。 (例如,typeof(Outer.Nested).FullName将返回这样的名称。)

我不确定这是否是指定的行为,或者只是微软C#编译器选择使用的方式;在正常的C#中,您无法明确声明带有+的类,因此编译器知道它不会与其他任何内容发生冲突。 根据我所见,C# 3规范的第10.3.8节并未规定编译后的名称。

编辑:我刚刚看到Type.AssemblyQualifiedName指定“+”用于前导嵌套类型名称...但仍不清楚这是否实际上是必需还是惯例。


2
这种实现细节的另一种表现形式是嵌套泛型类型。如果你有一个带有嵌套类Inner<U>的Outer<T>类,你会发现在元数据中实际上得到的是两种类型,Outer<1>和Outer+Inner<2>。从CLR的角度来看,嵌套类型实际上只是语言告诉我们的一个方便的谎言。嵌套体现在内部类型能够访问外部类型的私有成员的能力上。(命名空间也是类似的虚构概念。) - Eric Lippert
divo:我会认为Mono的C#编译器遵循与Microsoft相同的方案。同样,在C#规范中未指定某些内容的任何其他地方也是如此。 - Chris Charabaruk
1
@divo:和Chris一样,我强烈怀疑Mono遵循与MS编译器相同的方案。然而,在大多数情况下,这并不会引起注意 - 只有当您实际上需要通过完整名称作为字符串引用类型时才会出现。我并不经常这样做... - Jon Skeet
1
@Eric:嵌套类型是否因名称而获得特殊访问权限,还是元数据中有一个字段用于此?这个字段是否可以用于创建类似于C++的“友元类”? - Ben Voigt
2
ECMA CLI规范的10.7.2节提到:“虽然在元数据中编码的类型名称没有明确提到其封闭类型,但CIL和Reflection类型名称语法包括了这个细节”,随后列出了一个示例表格,其中包括词汇名称(例如X.Y),元数据编码(例如Y),CIL名称(例如X/Y)和Reflection名称(例如X+Y)。 - kvb
显示剩余5条评论

13

这是编译器在元数据中用于表示嵌套类的内容。

即:

class A { class B {} }

会被视为

class A+B

在元数据中


1
谢谢。这是我们能以这种方式找到的唯一标志吗? - Graveen
我刚刚在ILDASM中查看了.NET(1.1)库,并且其中的嵌套类型显示为'/'作为分隔符。 - Conrad Albrecht
1
@Ben - ILDASM并没有说谎,只是CIL和Reflection有不同的类型名称语法。请看我在Jon的帖子上的评论。 - kvb
1
@kvb:这些名称中有一个比其他名称更重要,因为它是无论语言如何都会公开的:反射名称。所有其他名称都是特定于语言的。“X.Y”不是“词法名称”,它只是一个词法名称(另一个词法名称是“X :: Y”,来自C++ / CLI,“X / Y”也是来自IL的词法名称)。 “词法”一词应该是一个很大的提示,因为词法分析是一项以语言为中心的任务。 - Ben Voigt
2
@Ben - 这很公平;你可以向规范编写者提出来 :) 我只是引用他们的表格。无论如何,我认为声称 ILDASM 是“撒谎”的说法有点过头了。它只是有自己的类型语法。 - kvb

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接