Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Nullable int in Attribute Constructor or Property

Tags:

c#

So I have a custom attribute, let's call it MyCustomAttribute, which has a constructor like so:

public MyCustomAttribute(int? i) {    // Code goes here } 

and declares a property:

public int? DefaultProperty { get; set; } 

Now if I wanted to use the property, I'd need to pass in an int or null, well that's what I'd expect.

But this gives a compiler error:

[MyCustomAttribute(1, DefaultProperty = 1)] public int? MyProperty { get; set; } 

and so does this:

[MyCustomAttribute(null,DefaultProperty = null)] public int? MyProperty { get; set; } 

The error is: An attribute argument must be a constant expression, typeof expression or array creation expression of an attribute parameter type for both the constructor and the property.

Why is this? If I change the constructor to take an int, I can pass in 0, but not null, which sort of defeats the purpose of the value (which can sometimes be null)

like image 390
PostMan Avatar asked Sep 21 '10 23:09

PostMan


People also ask

Is nullable int a reference type?

Nullable types represent value-type variables that can be assigned the value of null. You cannot create a nullable type based on a reference type. (Reference types already support the null value.) So, no they're not reference types.

How do you declare a nullable int?

You can declare nullable types using Nullable<t> where T is a type. Nullable<int> i = null; A nullable type can represent the correct range of values for its underlying value type, plus an additional null value. For example, Nullable<int> can be assigned any value from -2147483648 to 2147483647, or a null value.

How do I make my class property nullable in C#?

In C# and Visual Basic, you mark a value type as nullable by using the ? notation after the value type. For example, int? in C# or Integer? in Visual Basic declares an integer value type that can be assigned null . The Nullable class provides complementary support for the Nullable<T> structure.

What is default of nullable int?

The default value of a nullable value type represents null , that is, it's an instance whose Nullable<T>. HasValue property returns false .


1 Answers

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.

like image 107
JaredPar Avatar answered Sep 18 '22 17:09

JaredPar