Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is a Nullable<T> not a valid Custom Attribute Parameter when T is?

If I have an enum like this

public enum Hungry
{
    Somewhat,
    Very,
    CouldEatMySocks
}

and a custom attribute like this

public class HungerAttribute : Attribute
{
    public Hungry HungerLevel { get; set; }
    public Hungry? NullableHungerLevel { get; set; }
}

I can do this

[Hunger(HungerLevel = Hungry.CouldEatMySocks)]
public class Thing1

but I can't do this

[Hunger(NullableHungerLevel = Hungry.CouldEatMySocks)]
public class Thing2

It generates an error that says "'NullableHungerLevel' is not a valid named attribute argument because it is not a valid attribute parameter type".

Why is that not allowed? I understand that fundamentally it just isn't on the list of accepted types. The valid types seem to be primitives, enums, string, type, and one dimensional arrays of the preceding types.

Is this just an old rule that did not get updated when Nullable came along?

like image 382
Mike Two Avatar asked Sep 12 '09 21:09

Mike Two


3 Answers

Hungry? is equal to Nullable<Hungry>, which in terms mean that

[Hunger(NullableHungerLevel = Hungry.CouldEatMySocks)]

is equal to

[Hunger(NullableHungerLevel = new Nullable<Hungry>(Hungry.CouldEatMySocks))]

Since you can only use constant values in named attribute arguments you will have to resort to Shimmy's solution.

like image 169
Lars Udengaard Avatar answered Sep 29 '22 23:09

Lars Udengaard


To get around this create another initializer in your Attribute:

class Program
{
  [Hunger()]
  static void Main(string[] args)
  {
  }

  public sealed class HungerAttribute : Attribute
  {        
    public Hungry? HungerLevel { get; }
    public bool IsNull => !_HungerLevel.HasValue;

    public HungerAttribute()
    {
    }

    //Or:
    public HungerAttribute(Hungry level)
    {
      HungerLevel = level;
    }
  }

  public enum Hungry { Somewhat, Very, CouldEatMySocks }
}

I understand that you're not going to use both properties.

like image 27
Shimmy Weitzhandler Avatar answered Sep 29 '22 22:09

Shimmy Weitzhandler


Attributes may have as only parameters primitives, typeof expressions and array-creation expression.

Nullable is a struct.

Therefore it is not allowed there.

I suspect the assembly file format itself doesn't allow storage of complex types like structs in the place where attribute values are stored.

I don't know of any plans to change that. But I cannot explain why this restriction exist.

like image 37
codymanix Avatar answered Sep 29 '22 22:09

codymanix