【问题标题】:Is this an C# 4.0 compiler optional parameters bug?这是 C# 4.0 编译器可选参数错误吗?
【发布时间】:2011-06-17 22:29:21
【问题描述】:

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

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

我遇到了编译器错误:

错误: 'Foo属性' 不包含构造函数 接受 0 个参数

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

【问题讨论】:

  • 源码中的FooAttribute和报错信息中的DebugCallTraceAttribute是什么关系?
  • 第一个sn-p中的SecurityAttribute和第二个sn-p中的CodeAccessSecurityAttribute是否有原因?对于有效的最小测试用例,似乎这些应该是相同的。 (例如,它与此更改有关还是在两个文件中或两者兼而有之?)
  • 抱歉,莫斯科凌晨 3 点,所有 sn-p 错误都已修复
  • 非常酷的错误。如果 Eric 没有出现,请在 connect.microsoft.com 上发布。请张贴链接,很想知道这是怎么回事。您需要修复编译器错误 sn -p btw,它与您的代码不匹配。

标签: c# c#-4.0 attributes optional-parameters


【解决方案1】:

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

.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 上提交它作为建议的 cmets 之一,因为它似乎是由遍历的顺序引起的错误。

【讨论】:

  • 如果所有错误报告都得到如此充分的研究和编写!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多