选择Enum类型的默认值而不必更改值

xyz*_*xyz 198 .net c# enums

在C#中,是否可以使用属性修饰Enum类型或执行其他操作来指定默认值应该是什么,而不更改值?无论出于何种原因,所需的数字可能都是一成不变的,并且仍然可以控制默认值.

enum Orientation
{
    None = -1,
    North = 0,
    East = 1,
    South = 2,
    West = 3
}

Orientation o; // Is 'North' by default.
Run Code Online (Sandbox Code Playgroud)

Jam*_*ran 332

enum(实际上,任何值类型)的默认值为0 - 即使它不是有效值enum.它无法改变.

  • 重新提出这个问题,要求int的默认值为42.想想听起来有多愚蠢......在你得到它之前,运行时内存被*消隐了,枚举是结构记住的 (13认同)
  • 这些评论让我对这个答案持怀疑态度,所以我对它进行了测试,并确认这个答案肯定是正确的. (7认同)
  • @DougS 1.不,但承认你错了.他没有从评论票上获得任何声誉. (3认同)

小智 62

任何枚举的默认值为零.因此,如果要将一个枚举器设置为默认值,则将其设置为零,将所有其他枚举器设置为非零(如果有多个枚举器,则第一个枚举值为零的第一个枚举器将是该枚举的默认值值为零).

enum Orientation
{
    None = 0, //default value since it has the value '0'
    North = 1,
    East = 2,
    South = 3,
    West = 4
}

Orientation o; // initialized to 'None'
Run Code Online (Sandbox Code Playgroud)

如果您的枚举器不需要显式值,那么只需确保第一个枚举器是您想要成为默认枚举器的枚举器,因为"默认情况下,第一个枚举器的值为0,每个连续枚举器的值增加为1." (C#参考)

enum Orientation
{
    None, //default value since it is the first enumerator
    North,
    East,
    South,
    West
}

Orientation o; // initialized to 'None'
Run Code Online (Sandbox Code Playgroud)


Dav*_*vid 36

如果零不能作为正确的默认值,则可以使用组件模型为枚举定义变通方法:

[DefaultValue(None)]
public enum Orientation
{
     None = -1,
     North = 0,
     East = 1,
     South = 2,
     West = 3
 }

public static class Utilities
{
    public static TEnum GetDefaultValue<TEnum>() where TEnum : struct
    {
        Type t = typeof(TEnum);
        DefaultValueAttribute[] attributes = (DefaultValueAttribute[])t.GetCustomAttributes(typeof(DefaultValueAttribute), false);
        if (attributes != null &&
            attributes.Length > 0)
        {
            return (TEnum)attributes[0].Value;
        }
        else
        {
            return default(TEnum);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

然后你可以打电话:

Orientation o = Utilities.GetDefaultValue<Orientation>();
System.Diagnostics.Debug.Print(o.ToString());
Run Code Online (Sandbox Code Playgroud)

注意:您需要在文件顶部包含以下行:

using System.ComponentModel;
Run Code Online (Sandbox Code Playgroud)

这不会更改枚举的实际C#语言默认值,但会提供一种指示(并获取)所需默认值的方法.

  • +1用于重用组件模型属性和清洁解决方案.我建议你更改`else`语句中的最后一行,如下所示:`return default(TEnum);`.Fist,它将减少较慢的'Enum.GetValues(...).***`调用,第二个(更重要的是)它对任何类型都是通用的,甚至是非枚举.此外,您不限制仅用于枚举的代码,因此当使用非枚举类型时,这实际上将修复潜在的异常. (3认同)
  • 在MSDN文档中,确实没有任何组件模型或DefaultAttribute是仅“可视设计器”功能。作为公认的答案状态。简短的答案是“否,它不可能”,将枚举的默认值重新定义为0值以外的值。此答案是一种解决方法。 (2认同)

Joe*_*Joe 17

枚举的默认值是枚举等于零.我不相信这可以通过属性或其他方式改变.

(MSDN说:"枚举E的默认值是表达式(E)0产生的值.")

  • 严格来说,甚至不需要具有此值的枚举.零仍然是默认值. (12认同)

Avr*_*ram 11

你不能,但如果你愿意,你可以做一些技巧.:)

    public struct Orientation
    {
        ...
        public static Orientation None = -1;
        public static Orientation North = 0;
        public static Orientation East = 1;
        public static Orientation South = 2;
        public static Orientation West = 3;
    }
Run Code Online (Sandbox Code Playgroud)

这个结构的用法是简单的枚举.
你可以在哪里创建pa == Orientation.East(或你想要的任何值)默认
使用技巧本身,你需要通过代码转换int.
有实施:

        #region ConvertingToEnum
        private int val;
        static Dictionary<int, string> dict = null;

        public Orientation(int val)
        {
            this.val = val;
        }

        public static implicit operator Orientation(int value)
        {
            return new Orientation(value - 1);
        }

        public static bool operator ==(Orientation a, Orientation b)
        {
            return a.val == b.val;
        }

        public static bool operator !=(Orientation a, Orientation b)
        {
            return a.val != b.val;
        }

        public override string ToString()
        {
            if (dict == null)
                InitializeDict();
            if (dict.ContainsKey(val))
                return dict[val];
            return val.ToString();
        }

        private void InitializeDict()
        {
            dict = new Dictionary<int, string>();
            foreach (var fields in GetType().GetFields(BindingFlags.Public | BindingFlags.Static))
            {
                dict.Add(((Orientation)fields.GetValue(null)).val, fields.Name);
            }
        } 
        #endregion
Run Code Online (Sandbox Code Playgroud)


Dmi*_*lov 9

另一种可能有用的方法 - 使用某种"别名".例如:

public enum Status
{
    New = 10,
    Old = 20,
    Actual = 30,

    // Use Status.Default to specify default status in your code. 
    Default = New 
}
Run Code Online (Sandbox Code Playgroud)

  • 这个建议很好,但是,正如其他答案中已经提到的,枚举的默认值为零。在您的情况下,表达式 `Status s = default(Status);` 不会是任何状态成员,因为 `s` 的值为 `(Staus) 0`。后者可以直接写入,因为枚举可以转换为整数,但在反序列化期间会失败,因为框架确保枚举始终反序列化为有效成员。如果您将“New = 10”行更改为“New = 0”,您的代码将完全有效。 (2认同)
  • 是的。New = 0 会起作用。我个人会避免不明确设置枚举成员。 (2认同)

小智 6

实际上,enum默认enum值是其值的第一个元素0.

例如:

public enum Animals
{
    Cat,
    Dog,
    Pony = 0,
}
//its value will actually be Cat not Pony unless you assign a non zero value to Cat.
Animals animal;
Run Code Online (Sandbox Code Playgroud)

  • 实际上你应该:从不指定任何值或指定所有值或只指定第一个定义的成员的值.这里发生的是:Cat没有值,它是第一个值,因此自动将其设置为0.狗没有值,自动将其设置为PreviousValue + 1即1. Poney有一个值,保留值.所以Cat = Pony = 0,Dog = 1.如果你有{Cat,Dog,Pony = 0,Frog},那么Dog = Frog = 1. (16认同)
  • 但是,在那种情况下,"Pony"是"Cat"(例如,`Console.WriteLine(Animals.Pony);`打印"Cat") (9认同)