在属性构造函数中使用可选参数时,属性参数必须是常量错误

谁能解释为什么这段代码有效:

public class AdministratorSettingValidationAttribute : Attribute { public AdministratorSettingValidationAttribute(AdministratorSettingDataType administratorSettingDataType) { DataType = administratorSettingDataType; } public AdministratorSettingValidationAttribute(AdministratorSettingDataType administratorSettingDataType, Type enumerationType) { DataType = administratorSettingDataType; EnumerationType = enumerationType; } } 

…但重构它以使用可选参数:

  public AdministratorSettingValidationAttribute(AdministratorSettingDataType administratorSettingDataType, Type enumerationType = null) { DataType = administratorSettingDataType; EnumerationType = enumerationType; } 

…导致编译时错误:“ 属性参数必须是属性参数类型的常量表达式,typeof表达式或数组创建表达式 ”。

UPDATE

该漏洞已于去年7月报告并已修复。 该修复程序将出现在下一版本的C#中。 有关详细信息,请参阅此Connect反馈项:

http://connect.microsoft.com/VisualStudio/feedback/details/574497/optional-parameter-of-type-string-in-a-attribute-constructor-cannot-be-null


这显然是一个编译器错误。 谢谢你引起我的注意。

这里应该发生的是编译器应该意识到可选的值表达式被隐式转换为forms参数类型,然后将表达式视为该类型的常量表达式。 实际上它正在做的是将表达式视为无类型的空文字,这是错误的。

您可以通过将常量转换为明确键入的常量来解决错误:

 public AdministratorSettingValidationAttribute(AdministratorSettingDataType administratorSettingDataType, Type enumerationType = (Type)null) 

修复可能很简单,但我不能保证修复将在下一版本的C#中; 我不确定此时采取非关键错误修复的时间表是什么样的。

再次感谢,并为此带来的不便道歉。

这对我来说就像一个编译器错误。 属性类是“特殊”类,它们可以用作元数据。 C#编译器允许您以不同于普通类的方式使用它们,因此我们可以假设在C#编译器中存在用于编译属性类使用的(部分)自定义实现。 (任何人都可以在单声道上测试吗?)

也就是说,我做了一些测试,发现只有在使用属性的构造函数指定参数的默认值为null而不定义该属性的自定义值时,编译器才会给出错误。 我的测试代码:

 class TestAttribute : Attribute { public TestAttribute(object test = null) { } //public TestAttribute(int test = 0) { } public void TestMethod(object test = null) { } } class TestClass { public TestClass(object test = null) { } } [Test()] // crashes //[Test()] // Works when using the constructor taking an int //[Test(null)] // works class Program { static void Main(string[] args) { TestClass t = new TestClass(); // works TestAttribute a = typeof(Program).GetCustomAttributes(typeof(TestAttribute), false).Cast().First(); a.TestMethod(); // works } } 

(在.NET 4.0下使用VS 2010进行测试,任何人都可以用单声道测试吗?)

请注意,属性已经允许您将属性视为可选属性,因此您可以将可选参数设置为属性(如果尚未,则将其从构造函数中删除。这仍然允许您编写[Test(null,MyProperty = null) )]