属性构造函数或属性中的Nullable int

Pos*_*Man 24 c#

所以我有一个自定义属性,让我们调用它MyCustomAttribute,它有一个像这样的构造函数:

public MyCustomAttribute(int? i)
{
   // Code goes here
}
Run Code Online (Sandbox Code Playgroud)

并声明一个属性:

public int? DefaultProperty { get; set; }
Run Code Online (Sandbox Code Playgroud)

现在,如果我想使用该属性,我需要传入一个int或者null,这就是我所期望的.

但这会给编译器错误:

[MyCustomAttribute(1, DefaultProperty = 1)]
public int? MyProperty { get; set; }
Run Code Online (Sandbox Code Playgroud)

这样做:

[MyCustomAttribute(null,DefaultProperty = null)]
public int? MyProperty { get; set; }
Run Code Online (Sandbox Code Playgroud)

错误是:An attribute argument must be a constant expression, typeof expression or array creation expression of an attribute parameter type对于构造函数和属性.

为什么是这样?如果我改变构造函数以获取一个int,我可以传入0,但不是null,哪种方法会破坏值的目的(有时可能为null)

Jar*_*Par 24

之所以是,虽然双方0null是常数初始化构造函数的参数实际需要的表达是没有的.两者都需要转换为有效int?表达式.在引擎盖下它基本上产生以下

[MyCustomAttribute(new Nullable<int>(0))]
Run Code Online (Sandbox Code Playgroud)

该表达式不是常量,作为属性参数是不合法的

编辑

dtb询问这在属性值中是否非法为什么为可空参数设置默认参数是合法的?

void Example(int? x = null);
Run Code Online (Sandbox Code Playgroud)

您需要考虑的是解释价值的人/是什么.

对于属性参数,该值由CLR解释.自1.0以来,关于法律属性值的规则并没有真正改变.Nullable不存在,因此CLR不理解可空的初始化模式.

对于默认参数,vaule由方法的调用站点处的编译器解释.编译器理解可以为空的值,并且有更多的工作空间,因为它可以根据IL中的值在调用站点创建非常量表达式.

它是如何实际工作的?首先,编译器将实际编码常量,并null在IL中进行不同的编码

// x = 0 
[DefaultParameterValue(0)]
// x = null
[DefaultParameterValue(null)]
Run Code Online (Sandbox Code Playgroud)

在调用站点,编译器检查这些值并为参数值创建适当的(非常量)表达式.


Roe*_*gen 13

我知道问题是为什么,但对于重定向到此页面并正在寻求答案的开发人员.这是我的解决方法.

public class MyCustomAttribute: Attribute
{
    private Nullable<bool> myBoolean = null;

    public bool MyBooleanProperty { get { return this.myBoolean.GetValueOrDefault(); } set { this.myBoolean = value; } }
    public bool IsMyBooleanPropertySpecified { get { return this.myBoolean != null; } }
}
Run Code Online (Sandbox Code Playgroud)


Igo*_*aka 5

使用属性的经验法则是,他们采取的参数类型可以声明const关键字-即所有基本类型(intchar,等)和stringnew属性参数列表中不能使用任何关键字

您不能使用如下属性:

[Custom(new object())]
class Class {
}
Run Code Online (Sandbox Code Playgroud)

甚至是这样(即使DateTime是值类型):

[Custom(new DateTime(2001,1,1))]
class Class {
}
Run Code Online (Sandbox Code Playgroud)

因此Nullable<T>也不允许使用a ,因为传递null或1等效于执行以下操作:

[Custom(new Nullable<int>())]
//[Custom(null)]
class Class {
}
[Custom(new Nullable<int>(1))]
//[Custom(1)]
class Class {
}
Run Code Online (Sandbox Code Playgroud)