【问题标题】:Why is a Nullable<T> not a valid Custom Attribute Parameter when T is?为什么当 T 是 Nullable<T> 不是有效的自定义属性参数?
【发布时间】:2019-01-09 05:04:12
【问题描述】:

如果我有这样的枚举

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 出现时没有更新的旧规则吗?

【问题讨论】:

  • 虽然我最初在 .NET 3.5 VS2008 中遇到过这个问题,但在 VS2010 Beta1 中仍然无法使用。

标签: c# attributes nullable


【解决方案1】:

Hungry? 等于 Nullable&lt;Hungry&gt;,这意味着

[Hunger(NullableHungerLevel = Hungry.CouldEatMySocks)]

等于

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

由于您只能在命名属性参数中使用常量值,您将不得不求助于 Shimmy 的解决方案。

【讨论】:

  • 现在你解释它有点明显了!谢谢
【解决方案2】:

要解决这个问题,请在您的属性中创建另一个初始化程序:

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

我了解您不会同时使用这两个属性。

【讨论】:

  • 问题不是“我该怎么做”,而是“为什么”。这绝不是为什么。
  • 是的。这样可行。我知道如何解决它,但我很困惑为什么它不能作为命名参数工作。这对我来说似乎不一致。
  • 我应该删除这个答案吗?因为不幸的是我没有得到关于为什么部分的答案:(
  • @Shimmy。我个人会留下答案。它指出了在这种情况下正确的做法。如果其他人曾经搜索过该错误,这仍然很有用。它仍然有助于对话。如果您决定删除它,请将有关如何解决此问题的建议移至评论中。
【解决方案3】:

属性可以只包含原始参数、typeof 表达式和数组创建表达式。

Nullable 是一个结构。

所以那里是不允许的。

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

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

【讨论】:

    【解决方案4】:

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

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

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

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

    【讨论】:

      猜你喜欢
      • 2017-04-01
      • 2010-10-15
      • 1970-01-01
      • 1970-01-01
      • 2020-04-13
      • 1970-01-01
      • 2012-02-19
      • 1970-01-01
      相关资源
      最近更新 更多