2014-04-04 58 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