c#4.0-这是一个c#4.0编译器可选参数错误吗

本文关键字:c#4 编译器 参数 错误 一个 | 更新日期: 2023-09-27 17:59:22

我正在编写自定义安全属性,但遇到了奇怪的编译器行为。。。当我在同一个文件中使用属性时,默认参数值工作正常:

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) { }
}

我有一个编译器错误:

错误:"FooAttribute"不包含构造函数采用0个参数

这种情况只发生在CodeAccessSecurityAttribute继承人身上,看起来很奇怪。。。

c#4.0-这是一个c#4.0编译器可选参数错误吗

所以我没有确切的答案,但我已经尽我所能地研究了它。我想我理解为什么当你从CodeAccessSecurityAttribute而不是SecurityAttribute.继承时会发生这种情况。如果你看看在应用Foo属性时生成的IL,当它从CodeAccessSecurityAttribute继承时,它看起来是这样的:

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

Foo从SecurityAttribute继承时,它看起来像这样:

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

显然,CodeAccessSecurityAttribute极大地改变了通过应用该属性生成的IL。

如果我们将Foo声明更改为如下,请查看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) {}
 }

这告诉我的是,在构建过程中的某个地方存在问题。我对代码访问安全性是如何工作的还不够了解,无法确定确切的问题是什么。必须有一部分过程来查看CodeAccessSecurityAttributes,并尝试将SecurityAction应用于代码。我认为它为程序集构建了某种元数据。它必须以某种有序的方式执行此操作,这样它就不会看到可选参数,直到它已经通过了Program类之后。然后,它必须在构建过程中以某种方式使用该元数据,这就是您看到失败的地方。要了解更多细节,我们必须希望了解编译器的人,即Eric,能对它有所了解。我会在connect.microsoft.com上提交它,作为建议的注释之一,因为它似乎是由遍历顺序引起的错误。