代码之家  ›  专栏  ›  技术社区  ›  Mike Two

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

  •  23
  • Mike Two  · 技术社区  · 15 年前

    如果我有这样的枚举

    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 回复  |  直到 6 年前
        1
  •  28
  •   Shimmy Weitzhandler 500 - Internal Server Error    6 年前

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

    [Hunger(NullableHungerLevel = Hungry.CouldEatMySocks)]
    

    等于

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

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

        2
  •  22
  •   Shimmy Weitzhandler 500 - Internal Server Error    6 年前

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

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

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

        3
  •  6
  •   codymanix    15 年前

    属性只能具有参数原语、类型表达式和数组创建表达式。

    nullable是一个结构。

    因此不允许在那里。

    我怀疑程序集文件格式本身不允许在存储属性值的位置存储结构等复杂类型。

    我不知道有什么计划要改变这一点。但我不能解释为什么存在这种限制。

        4
  •  3
  •   Ariwibawa    8 年前

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

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

    在代码中,您可以这样做来检查是否为空

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