2011-06-17 104 views
13

我寫自定義安全特性,得到了奇怪的編譯器行爲......當我在使用相同的文件屬性,默認參數值正常工作:這是一個C#4.0編譯器可選參數的bug嗎?

using System.Security.Permissions; 

[System.Serializable] 
sealed class FooAttribute : CodeAccessSecurityAttribute { 
    public FooAttribute(SecurityAction action = SecurityAction.Demand) : base(action) { } 
    public override System.Security.IPermission CreatePermission() { return null; } 
} 

[Foo] class Program { 
    static void Main(string[] args) { } 
} 

但是當我分開的代碼以上爲兩個文件這樣的 - 文件1:

using System.Security.Permissions; 

[System.Serializable] 
sealed class FooAttribute : CodeAccessSecurityAttribute { 
    public FooAttribute(SecurityAction action = SecurityAction.Demand) : base(action) { } 
    public override System.Security.IPermission CreatePermission() { return null; } 
} 

和文件2:

[Foo] class Program { 
    static void Main(string[] args) { } 
} 

我有一個編譯器錯誤:

Error: 'FooAttribute' does not contain a constructor that takes 0 arguments

出現這種情況只與CodeAccessSecurityAttribute繼承人,看起來很奇怪...

+2

源代碼中的FooAttribute與錯誤消息中的DebugCallTraceAttribute之間的關係是什麼? –

+2

第二個代碼段中的「SecurityAttribute」和第二個代碼段中的CodeAccessSecurityAttribute是否有原因?似乎這些對於有效的最小測試用例應該是相同的。 (例如,它是與此更改相關還是與兩個文件或兩者兼而有之) – 2011-06-17 22:33:51

+0

對不起,在莫斯科凌晨3點,所有片段錯誤都已修復 – ControlFlow

回答

13

所以我沒有一個確切的答案,但我把它儘可能我可以尋找到它。我想我明白爲什麼當你從CodeAccessSecurityAttribute繼承,而不是SecurityAttribute.如果你看看IL產生碰巧應用Foo屬性時,當它從CodeAccessSecurityAttribute繼承它看起來像這樣:

.permissionset demand = {class 'ConsoleApplication1.FooAttribute, ConsoleApplication1, Version=1.0.0.0, Culture=neutral' = {}} 

從SecurityAttribute什麼時候Foo繼承看起來像這樣:

.custom instance void ConsoleApplication1.FooAttribute::.ctor(valuetype [mscorlib]System.Security.Permissions.SecurityAction) = (01 00 02 00 00 00 00 00) 

顯然,CodeAccessSecurityAttribute顯着地改變了通過應用該屬性而生成的IL。

在IL尋找更多,如果我們改變了美孚宣佈要像如下

[Foo(SecurityAction.Demand)] 

我們得到以下IL:

.permissionset demand = {class 'ConsoleApplication1.FooAttribute, ConsoleApplication1, Version=1.0.0.0, Culture=neutral' = {}} 

其相同,因爲它是我們沒有指定可選參數。再者,我們不能僅僅通過拆分屬性和Program類爲獨立的文件會導致錯誤,我們可以通過類這樣的重新安排文件會導致它:

[Foo] 
class Program 
{ 

    static void Main(string[] args) {} 


} 

[System.Serializable] 
sealed class FooAttribute : CodeAccessSecurityAttribute 
{ 
    public FooAttribute(SecurityAction action = SecurityAction.Demand) : base(action) { } 
    public override System.Security.IPermission CreatePermission() { return null; } 
} 

更有趣的,如果我們的帶班以下OtherOther2給出了錯誤,但Program沒有。只有在文件中Foo來之前的類將有錯誤

[Foo] 
class Other 
{ 

} 

[Foo] 
class Other2 
{ 
} 

[System.Serializable] 
sealed class FooAttribute : CodeAccessSecurityAttribute 
{ 
     public FooAttribute(SecurityAction action = SecurityAction.Demand) : base(action) { } 
     public override System.Security.IPermission CreatePermission() { return null; }  } 

[Foo] 
class Program 
{ 

    static void Main(string[] args) {} 
} 

這是什麼對我說的是,有問題的地方在構建過程中。我對Code Access Security的工作原理並不十分了解,因此我不知道具體問題是什麼。必須有部分流程查看CodeAccessSecurityAttributes,並嘗試將SecurityAction應用於代碼。我假設它爲程序集構建了某種元數據。它必須以某種有序的方式做到這一點,以便在它已經通過Program類之後才能看到可選參數。然後,它必須在構建過程中以某種方式使用該元數據,這就是您看到失敗的地方。對於任何更多的細節,我們都不得不希望知道編譯器的人,即埃裏克能夠闡明它。我會在connect.microsoft.com上提交它作爲其中的一條評論,因爲它似乎是由遍歷命令造成的錯誤。

+1

+1從我進行良好的分析。 – Jehof

+0

如果只有**所有**錯誤報告被如此精心研究和編寫! –