【问题标题】:How to tell if an enum property has been set? C#如何判断枚举属性是否已设置? C#
【发布时间】:2013-05-09 09:45:51
【问题描述】:

我有一个这样的枚举属性类:

public class Foo
{
    public Color ColorType {get;set;}
}

public enum Color
{
    Red,
    Green,
}

现在这个类可以这样初始化:

var foo = new Foo();

没有设置 ColorType 属性。 现在,我正在尝试创建一个方法并对该枚举是否已设置执行操作,例如我有一个方法

private void checkEnum(Foo foo)
{
    if(foo.ColorType !=null)
    {
        //perform these actions
    }else
    {
        //perform those actions
    }
}

但是我收到一条警告说值永远不会为空,并且在进一步研究后,如果从未设置枚举,如果将默认为第一个值,这将 在我的情况下是红色的,我正在考虑向我的枚举添加一个“未设置”的值并将该值设为第一个,所以如果它还没有设置 枚举的值将是“未设置”,有没有更好的方法来做到这一点,我提出的方法似乎会变得混乱

【问题讨论】:

标签: c# properties enums set


【解决方案1】:

您可以使用以下两种方法之一:默认枚举值或可为空的枚举。

默认枚举值

由于枚举由整数支持,并且int 默认为零,因此枚举将始终默认初始化为等于零的值。除非您明确分配枚举值,否则第一个值将始终为零,第二个值将是 1,依此类推。

public enum Color
{
  Undefined,
  Red,
  Green
}

// ...

Assert.IsTrue(Color.Undefined == 0);  // success!

可为空的枚举

处理未分配枚举的另一种方法是使用可为空的字段。

public class Foo
{
   public Color? Color { get; set; }
}

// ...

var foo = new Foo();
Assert.IsNull(foo.Color);     // success!

【讨论】:

  • 很好的答案,但它无法解决用户能够将值设置为 null 或 undefined 的问题,因此您不知道用户是否将枚举设置为此或者枚举是否有没有改变。
  • @MrUniverse true,您可以引入一个布尔标志字段,该字段在第一次更改 Color 值时设置。但是,您必须小心,并确保该类不会以使其误报的方式反序列化。
  • 如果在调用 setter 时设置为 true 的属性(如 [UserModifiedMonitor])会怎样?我不认为属性会被类反序列化。
  • @MrUniverse 我不知道你是否可以在运行时动态设置属性值,但即使你可以,这似乎是对属性基础设施的一种相当暴力的滥用,这是关于静态的注释而不是动态状态。
  • 好吧,静态注释是您将其标记为受监控的集合属性。至于物理限制,属性(大部分)只是附加到属性(或其他结构)的对象。所以它会起作用。
【解决方案2】:

您可以使底层私有字段可以为空,但属性不能。

例如

class SomeClass
{
    private Color? _color; // defaults to null

    public Color Color
    {
        get { return _color ?? Color.Black; }
        set { _color = value; }
    }

    public bool ColorChanged
    {
        get { return _color != null; }
    }
}

这样,如果color == null 您知道它尚未设置,并且您还阻止用户将其设置为null(或undefined,如其他答案所指定)。如果colornull,则您100% 确定用户从未设置过它。

只有 catch 是 get 返回的默认值,但如果它更好地匹配您的程序,您总是可以抛出异常。

您还可以更进一步,使set 仅在给定值不等于默认值时设置字段(取决于您的用例):

public Color Color
{
    get { return _color ?? Color.Black; }
    set
    {
        if (value != Color)
        {
            _color = value;
        }
    }
}

【讨论】:

  • 你甚至可以做return color ?? Color.Black
  • @1blustone 谢谢,已修复并对答案进行了一些一般性改进。
【解决方案3】:

你有两个真正的选择。第一种是给枚举添加一个未定义的值。这将是属性初始化之前的默认值。

1)

public enum Color
{
    Undefined,
    Red,
    Green,
}

您的支票如下:

private void checkEnum(Foo foo)
{
    if(foo.ColorType == Color.Undefined)
    {
        //perform these actions
    }else
    {
        //perform those actions
    }
}

2) 或者,您不能添加未定义的值,只需将属性设为Nullable

public class Foo
{
    public Color? ColorType {get;set;}
}
public enum Color
{
    Red,
    Green,
}

然后像这样进行检查:

private void checkEnum(Foo foo)
{
    if(!foo.ColorType.HasValue)
    {
        //perform these actions
    }else
    {
        //perform those actions
    }
}

【讨论】:

    【解决方案4】:

    枚举是Value Types,这意味着它们不是对存储在其他地方的对象的引用,因此它们不能是null。它们总是有一个默认值,就像 int 在创建时默认为零。我建议两种方法:

    1. 添加另一个枚举条目,例如,None,其值等于 0。这样,您的枚举值将在创建时默认为 None。然后可以查看if(foo.ColorType != Color.None)

    2. 将您的 Color 属性设为可为空的,例如:public Color? ColorType { get; set; }。现在它将默认为null,并且可以分配值null。在此处阅读有关nullable 类型的更多信息:MSDN - Nullable Types (C#)

    【讨论】:

      【解决方案5】:

      正如您所发现的,C# 中的枚举是值类型(它们本质上是整数)而不是引用类型,因此它们不会默认为 NULL,而是枚举中的最低整数值。在处理枚举时不要忽视这种关系,因为它是它们最有用的属性之一。永远记住,无论您是否明确声明,

      public enum Color
      {
          Red,
          Green
      }
      

      等于:

      public enum Color
      {
          Red = 0,
          Green = 1
      }
      

      虽然你当然可以给每个枚举成员任何你喜欢的整数值。

      至于是否有更好的方法来做到这一点,这实际上完全取决于“this”是什么,尽管您建议简单地使用以下枚举设置并没有错:

      public enum Color
      {
          None = 0,
          Red,
          Green
      }
      

      通常,当您希望能够按名称从中进行选择的一组绝对有限且离散的可能值时,您希望使用枚举。例如,假设我有一个将 4 个基本方向(北、东、南、西)之一作为参数的方法。我决定要按顺时针顺序对每个方向进行编号,从 0 开始表示北。

      public enum Direction
      {
          North = 0,
          East,
          South,
          West
      }
      

      现在,与其让我的函数接受一个整数参数并相信我会记住每个数字所指的内容,我现在可以让该函数接受一个枚举成员作为参数并立即知道我正在处理的方向.例如:

      getNeighbor(1);
      

      读起来更容易:

      getNeighbor(Direction.East);
      

      【讨论】:

        【解决方案6】:

        enum是值类型,不能为null,存储一般为整数。如果你想为你的类型定义一个未定义的值,你可能有

        public enum Color
        {
            Undefined,
            Red,
            Green,
        }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2012-05-09
          • 2012-06-09
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多