The reason why is that while both 0
and null
are constant the actual expression needed to initialize the constructor parameter is not. Both require a conversion to be a valid int?
expression. Under the hood it essentially generates the following
[MyCustomAttribute(new Nullable<int>(0))]
This expression not being constant is not legal as an attribute argument
EDIT
dtb asked if this is illegal in attribute values why is it legal to have a default parameter for a nullable parameter?
void Example(int? x = null);
What you need to consider is who / what is interpreting the values.
For attributes arguments the value is interpreted by the CLR. The rules concerning legal attribute values haven’t really changed since 1.0. Nullable didn’t exist then hence the CLR doesn’t understand nullable initialization patterns.
For default arguments the value is interpreted by the compiler at the call site of the method. The compilers understands nullable values and has a bit more room to work with as it can create non-constant expressions at the call site based on the values in IL.
How does it actually work though? First the compiler will actually encode constants and null
differently in IL
// x = 0
[DefaultParameterValue(0)]
// x = null
[DefaultParameterValue(null)]
At the call site the compiler examines these values and creates the appropriate (non-constant) expression for the parameter value.