当T为?</t>时,为什么Nullable <t>不是有效的自定义属性参数

时间:2009-09-12 21:01:48

标签: c# attributes nullable

如果我有这样的枚举

public enum Hungry
{
    Somewhat,
    Very,
    CouldEatMySocks
}

以及像这样的自定义属性

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

我可以这样做

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

但我不能这样做

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

它会生成一个错误,指出“'NullableHungerLevel'不是有效的命名属性参数,因为它不是有效的属性参数类型”。

为什么不允许这样做?据我所知,从根本上说它不在可接受的类型列表中。有效类型似乎是基元,枚举,字符串,类型和前面类型的一维数组。

这只是一个旧规则,当Nullable出现时没有得到更新吗?

4 个答案:

答案 0 :(得分:28)

Hungry?等于Nullable<Hungry>,这意味着

[Hunger(NullableHungerLevel = Hungry.CouldEatMySocks)]

等于

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

由于您只能在命名属性参数中使用常量值,因此您必须使用Shimmy的解决方案。

答案 1 :(得分:22)

要解决此问题,请在属性中创建另一个初始值设定项:

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 }
}

我知道您不会同时使用这两种属性。

答案 2 :(得分:6)

属性可以仅包含参数基元,类型表达式和数组创建表达式。

Nullable是一个结构。

因此不允许在那里。

我怀疑汇编文件格式本身不允许在存储属性值的地方存储复杂类型,例如结构。

我不知道有任何改变它的计划。但我无法解释为什么存在这种限制。

答案 3 :(得分:3)

您可以为该枚举创建默认值,而不是创建可为空的枚举。枚举从第一个值中选择默认值,因此请设置这样的枚举

public enum Hungry
{
    None,
    Somewhat,
    Very,
    CouldEatMySocks
}

在您的代码中,您可以执行此操作以检查null

if(default(Hungry) == HungerLevel)//no value has been set