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

Jon*_*att 17 .net c# visual-studio-2010

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

public class AdministratorSettingValidationAttribute : Attribute
{
    public AdministratorSettingValidationAttribute(AdministratorSettingDataType administratorSettingDataType)
    {
        DataType = administratorSettingDataType;
    }

    public AdministratorSettingValidationAttribute(AdministratorSettingDataType administratorSettingDataType, Type enumerationType)
    {
        DataType = administratorSettingDataType;
        EnumerationType = enumerationType;
    }
}
Run Code Online (Sandbox Code Playgroud)

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

    public AdministratorSettingValidationAttribute(AdministratorSettingDataType administratorSettingDataType, Type enumerationType = null)
    {
        DataType = administratorSettingDataType;
        EnumerationType = enumerationType;
    }
Run Code Online (Sandbox Code Playgroud)

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

Eri*_*ert 19

UPDATE

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

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


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

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

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

public AdministratorSettingValidationAttribute(AdministratorSettingDataType administratorSettingDataType, Type enumerationType = (Type)null) 
Run Code Online (Sandbox Code Playgroud)

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

再次感谢,并为此带来的不便表示歉意.

  • 正如我对上述答案的评论中所指出的,Mono处理代码很好,所以它特定于Visual C#编译器. (2认同)

Pol*_*ity 5

这对我来说就像一个编译器错误.属性类是"特殊"类,它们可以用作元数据.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<TestAttribute>().First();

        a.TestMethod(); // works
    }
}
Run Code Online (Sandbox Code Playgroud)

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

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