Nullable value types in C# attributes
Attributes in C# support only a limited number of parameter types. If you want to use other types, such as Nullable<int>
, you must find a way around this limitation.
Attribute classes can have properties of other types:
[AttributeUsage(AttributeTargets.Class, AllowMultiple = true)]
public class MyAttribute : Attribute
{
public int? NullableParameter { get; set; }
}
But you cannot set them for an attribute instance:
[My(NullableParameter = 1)]
public record MyRecord();
The compiler complains with the following error message:
CS0655:
NullableParameter
is not a valid named attribute argument because it is not a valid attribute parameter type
You could try to add a constructor with an optional parameter to the attribute class:
[AttributeUsage(AttributeTargets.Class, AllowMultiple = true)]
public class MyAttribute : Attribute
{
public MyAttribute(int? nullableParameter = null)
{
NullableParameter = nullableParameter;
}
public int? NullableParameter { get; set; }
}
But the compiler will not allow you to use this constructor:
[My(nullableParameter: 1)]
public record MyRecord();
It will complain with a slightly different error message:
CS0181: Attribute constructor parameter
nullableParameter
has typeint?
, which is not a valid attribute parameter type
Instead of adding a constructor with an optional parameter of type Nullable<int>
, you can add two constructors to achieve the same thing without using the unsupported type Nullable<int>
:
public class MyAttribute : Attribute
{
public MyAttribute() { }
public MyAttribute(int nullableParameter)
{
NullableParameter = nullableParameter;
}
public int? NullableParameter { get; set; }
}
The compiler allows you to use these two constructors because they have no parameters of unsupported types:
[My()]
[My(nullableParameter: 1)]
public record MyRecord();
I have put an example project with this approach in my GitHub repository.
Attributes in C# have many limitations, but with creativity you can work around some of them. In this post, I described a possible approach to using nullable value types.