简体   繁体   English

如何判断枚举属性是否已设置? C#

[英]How to tell if an enum property has been set? C#

I have a class with an enum property like so:我有一个 class,它的枚举属性如下:

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

public enum Color
{
    Red,
    Green,
}

Now this class can be initialized like so:现在这个 class 可以像这样初始化:

var foo = new Foo();

without the ColorType property ever being set.没有设置 ColorType 属性。 Now, I'm trying to create a method and perform actions on whether that enum was ever set or not, for example I have a method现在,我正在尝试创建一个方法并对是否设置过该枚举执行操作,例如我有一个方法

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

however I get a warning saying that value will never be null and upon further research, if the enum is never set if will default to the first value which would be Red in my case, I was thinking about adding a value to my enum which would be 'not set' and make that value the first one, so if it hasnt been set then the enum will have the value 'not set', is there a better way of doing this, my proposed method seems like it could get messy但是我收到一条警告说该值永远不会是 null 并且经过进一步研究,如果从未设置枚举如果将默认为第一个值,在我的情况下将是红色,我正在考虑向我的枚举添加一个值这将“未设置”并将该值设置为第一个,因此如果尚未设置,则枚举将具有“未设置”的值,是否有更好的方法来执行此操作,我提出的方法似乎会变得混乱

You can use one of two methods: default enum value or a nullable enum.您可以使用以下两种方法之一:默认枚举值或可为空的枚举。

Default enum value默认枚举值

Since an enum is backed by an integer, and int defaults to zero, the enum will always initialize by default to the value equivalent to zero.由于枚举由整数支持,并且int默认为零,因此默认情况下枚举将始终初始化为等效于零的值。 Unless you explicitly assign enum values, the first value will always be zero, second will be one, and so on.除非您明确分配枚举值,否则第一个值将始终为零,第二个值为 1,依此类推。

public enum Color
{
  Undefined,
  Red,
  Green
}

// ...

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

Nullable enum可为空的枚举

The other way to handle unassigned enum is to use a nullable field.处理未分配枚举的另一种方法是使用可为空的字段。

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

// ...

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

You can make it so that the underlying private field is nullable, but the property is not.您可以使基础私有字段可以为空,但属性不是。

Eg例如

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

That way if color == null you know it hasn't been set yet, and you are also stopping the user from setting it to null (or undefined as other answers specify).这样,如果color == null您知道它尚未设置,并且您还阻止用户将其设置为null (或undefined为其他答案指定)。 If color is null you have 100% certainty that the user has not set it ever.如果colornull您 100% 确定用户从未设置过它。

Only catch is the default value returned by the get but you could always throw an excepting if it better matches your program.只有 catch 是get返回的默认值,但如果它更好地匹配您的程序,您总是可以抛出异常。

You can also take it one step further by making it so that the set only sets the field if the given value is not equal to the default value (depending on your use case):您还可以通过使其更进一步,以便set仅在给定值不等于默认值时设置字段(取决于您的用例):

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

You have two real options.你有两个真正的选择。 The first is to add an undefined value to enum.第一个是向枚举添加一个未定义的值。 This will be the default value before the property is initialized.这将是属性初始化之前的默认值。

1) 1)

public enum Color
{
    Undefined,
    Red,
    Green,
}

With your check like:用你的支票:

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

2) Alternatively you can not add the undefined value and just make the property Nullable 2) 或者,您不能添加未定义的值,而只能将属性Nullable

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

And perform your check like:并执行您的检查,如:

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

Enums are Value Types , which means they are not references to an object stored somewhere else, and hence they cannot be null .枚举是值类型,这意味着它们不是对存储在其他地方的对象的引用,因此它们不能为null They always have a default value just like int which will default to zero upon creation.它们总是有一个默认值,就像int一样,在创建时默认为零。 I suggest two approaches:我建议两种方法:

  1. Add another enum entry called eg, None with value equal to zero.添加另一个名为例如None枚举条目,其值等于零。 This way your enum value will default to None upon creation.这样你的枚举值在创建时将默认为None Then you can check if(foo.ColorType != Color.None) .然后你可以检查if(foo.ColorType != Color.None)

  2. Make your Color property a nullable one like: public Color? ColorType { get; set; }使您的Color属性成为可空属性,例如: public Color? ColorType { get; set; } public Color? ColorType { get; set; } public Color? ColorType { get; set; } . public Color? ColorType { get; set; } . Now it will default to null and can be assigned the value null .现在它将默认为null并且可以分配值null Read more about nullable types here: MSDN - Nullable Types (C#) .在此处阅读有关nullable类型的更多信息: MSDN - Nullable Types (C#)

Try this:尝试这个:

private void checkEnum(Color color)
{
    if(string.IsNullOrEmpty(color.ToString()))
    {
        //value is not set
    }
     else
    {
        //value is set
    }
}

enum is a value type so it cannot be null, and the storage is generally an integer. enum是值类型所以不能为null,存储一般是整数。 If you want a undefined value for your type, you may have如果你想要一个未定义的类型值,你可能有

public enum Color
{
    Undefined,
    Red,
    Green,
}

As you've discovered, enumerations in C# are value types (they are essentially integers) not reference types so they will not default to NULL but rather the lowest integer value in the enumeration.正如您所发现的,C# 中的枚举是值类型(它们本质上是整数)而不是引用类型,因此它们不会默认为 NULL,而是枚举中最低的整数值。 Don't lose sight of this relationship when dealing with enums as it's one of their most useful attributes.在处理枚举时不要忽视这种关系,因为这是它们最有用的属性之一。 Always remember that whether you explicitly state it or not,永远记住,无论你是否明确说明,

public enum Color
{
    Red,
    Green
}

equates to:相当于:

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

Though you may of course give each enumeration member any integer value that you like.尽管您当然可以为每个枚举成员提供您喜欢的任何整数值。

As far as whether or not there is a better way of doing this, it really all depends on what "this" is, though there's nothing wrong with your suggestion of simply using the following enum setup:至于是否有更好的方法来做到这一点,这实际上完全取决于“这个”是什么,尽管您建议简单地使用以下枚举设置并没有错:

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

Generally you want to use enums when you have a decidedly finite and discrete set of possible values that you want to be able to select from by name.通常,当您希望能够通过名称从中选择一组绝对有限且离散的可能值时,您希望使用枚举。 For example, say I have a method that takes one of the 4 cardinal directions (North, East, South, West) as a parameter.例如,假设我有一个方法,它将 4 个基本方向(北、东、南、西)之一作为参数。 I decide that I want to number each of the directions in clockwise order, starting with 0 for North.我决定按顺时针顺序对每个方向进行编号,从 0 开始表示北。

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

Now, instead of having my function take an integer parameter and trusting that I'll remember what each number refers to, I can now have the function take an enumeration member as a parameter and know immediately which direction I'm dealing with.现在,不是让我的函数采用整数参数并相信我会记住每个数字所指的内容,我现在可以让函数采用枚举成员作为参数并立即知道我正在处理的方向。 For example:例如:

getNeighbor(1);

reads much easier as:阅读起来更容易,因为:

getNeighbor(Direction.East);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM