2014-04-04 60 views
7

考虑一下:为什么在继承泛型类型时,必须使用父类型限定使用嵌套类型?

[SomeAttr(typeof(Bar))] 
class Foo { 

    class Bar { 

    } 
} 

...这:

class Foo : ISomething<Bar> { 

    class Bar { 

    } 
} 

第一个例子编译,第二个没有。要使用嵌套式引用从一个泛型类型继承时,我必须与家长的类型名称限定它:

class Foo : ISomething<Foo.Bar> { 

    class Bar { 

    } 
} 

我的问题是,为什么呢?以及为什么从父类型的属性引用时不适用此限制(第一个示例)?

+0

我的猜测是编译器在编译类之后处理类属性?但是我对编译器内部知识不够了解甚至不知道如何找到/证明答案。虽然非常有趣的问题! – BateTech

+0

以这种方式使用公共嵌套子类的实际例子是什么?为什么有一个嵌套类时,父类是依赖于孩子与只是使它在同一个名字空间的父类类? – BateTech

+0

@BateTech我在使用代码生成器时发现了这个限制,它只允许我在类内部注入代码来定义我自己的方法。 –

回答

6

这一切都是关于声明的范围。请看下面的代码:

namespace FooSpace 
{ 
    class Foo : ISomething<Bar> 
    { 
     class Bar { } 
    } 
} 

的代码class Foo : ISomething<Bar>该生产线是在FooSpace命名空间,但是Foo内不。此时,Bar没有意义。 Bar本身只有的范围范围内的Foo本身。

使用类Bar任何代码类,必须限定它作为Foo.Bar。此规则在类声明本身内也适用

这是为什么?难道编译器不能自动计算出您必须表示同一个类中嵌套的Bar

嗯,一件事有可能是其他嵌套类称为在同一个命名空间中的其他类中Bar,如下:

namespace FooSpace 
{ 
    class Foo : List<Foo.Bar> 
    { 
     public class Bar { } 
    } 

    class Foo2 : List<Foo2.Bar> 
    { 
     public class Bar { } 
    } 
} 

没有资格,你的意思是这Bar?编译器将无法告诉。因此,编译器不要试图猜测,而是要坚持一个明确限定的类名。

对于属性的情况下,虽然类靶向属性是声明类声明这样上面:

[SomeAttr(typeof(Bar))] 
class Foo { ... 

在现实中,编译器把这个东西更是这样的:

class public auto ansi beforefieldinit FooSpace.Foo extends [mscorlib]System.Object 
{ 
    .custom instance void FooSpace.SomeAttr::.ctor ... etc. 

也就是说,使用您提供的参数,实际的SomeAttr属性对象被创建为里面的类。该参数typeof(Bar)当然是有效的,因为它存在于Foo的类范围内。

相关问题here也讨论过这种情况。

有趣的是要注意的是完全相同的规则和行为所适用的访问常量或静态类成员类的属性 - 你不需要指定类名,因为该属性里面类实际创建

+0

这并不能解释为什么它与属性一起工作。 –

+0

这个答案很有意义,但并没有回答为什么父类的属性引用类“bar”成功编译。 – BateTech

+0

我会将其添加为编辑。 – Baldrick