枚举值隐藏在C#中

时间:2010-08-28 18:06:16

标签: c# enums

我有一个枚举,我想“隐藏”其中一个值(因为我将其添加以供将来支持)。 代码用C#编写。

public enum MyEnum
{
   ValueA = 0,

   ValueB = 1,

   Reserved
}

我不想允许使用此代码的人使用此值(MyEnum.Reserved)。 任何的想法? TIA

7 个答案:

答案 0 :(得分:9)

你可以使用'过时'属性 - 在语义上不正确,但它会做你想要的:

public enum MyEnum 
{ 
  ValueA = 0, 
  ValueB = 1, 
  [Obsolete("Do not use this", true)]
  Reserved 
}

任何尝试使用Foo.Reserved项目进行编译的人都会收到错误

答案 1 :(得分:5)

如果您不想展示它,请不要包含它:

public enum MyEnum
{
    ValueA = 0,
    ValueB = 1,
}

请注意,此枚举的用户仍然可以将任何整数值分配给声明为MyEnum的变量:

MyEnum e = (MyEnum)2;  // works!

这意味着接受枚举的方法应始终在使用之前验证此输入:

void DoIt(MyEnum e)
{
    if (e != MyEnum.ValueA && e != MyEnum.ValueB)
    {
        throw new ArgumentException();
    }

    // ...
}

因此,只需稍后在需要时添加您的值,然后修改您的方法以接受它。

答案 2 :(得分:2)

这在C#中是不可能的。如果可以访问Enum本身,则可以访问所有枚举值。

您可以模拟完成此操作的唯一方法是使用不太容易访问的静态字段,该字段使用Enum中尚未使用的整数值。

public enum MyEnum {
  ValueA = 0;
  ValueB = 1;
}

internal static class MyEnumEx {
  internal static MyEnum Reserved = (MyEnum)42;
}

我很好奇你为什么要这样做。无论您做什么,用户仍然可以提供Reserved值。所有需要做的就是将int适当的值转换为MyEnum类型。

// Code that shouldn't access Reserve
MyEnum reserved = (MyEnum)42;  // Woot!

答案 3 :(得分:2)

您可以使用自己的自定义类型而不是enum来实现 这样的内容:

// This type works pretty much the same way an enum works;
// each specific value can be cast to/from an int, and each has
// a specific name that is returned on calling ToString().
public sealed class MyEnum
{
    private readonly int _value;
    private readonly string _name;

    // private constructor -- ensure that the static members you define below
    // are the only MyEnum instances accessible from any outside code
    private MyEnum(int value, string name)
    {
        _value = value;
        _name = name;
    }

    // no need to override Equals or GetHashCode, believe it or not --
    // one instance per value means we can use reference equality and
    // that should be just fine
    public override string ToString()
    {
        return _name;
    }

    // provide direct access only to these members
    public static readonly MyEnum ValueA = new MyEnum(0, "ValueA");
    public static readonly MyEnum ValueB = new MyEnum(1, "ValueB");

    // this member is only available to you within the current assembly
    internal static readonly MyEnum Reserved = new MyEnum(-1, "Reserved");
}

您甚至可以进一步模拟enum值的行为,例如,重载explicit运算符以转换为MyEnum对象/从int对象转换为implicit值JaredPar建议使用此而不是public static explicit operator MyEnum(int value) { switch (value) { case 0: return ValueA; case 1: return ValueB; default: throw new InvalidCastException(); } } public static explicit operator int(MyEnum value) { return value._value; } ):

{{1}}

答案 4 :(得分:0)

您无法隐藏它,但您可以添加一个注释,此值此时没有任何效果。否则只需删除它并在添加支持时添加它,这不应该破坏任何其他依赖它的代码,只要原始值不会改变。

答案 5 :(得分:0)

您使用的是"隐藏"价值内部?如果不是:

public enum MyEnum
{
   ValueA = 0,
   ValueB = 1,
   //TODO: Reserved
}

通过定义未使用的变量,你什么也得不到。

答案 6 :(得分:0)

枚举Flags也有类似的问题,但是我使用的解决方案应该在没有Flags属性的情况下工作。

您可以创建两种枚举类型,一种用于保留值,另一种用于可公开使用的值。您可以将HasFlag与保留类型一起使用,而无需强制转换,但是分配需要强制转换。

[Flags]
public enum MyEnumReserved {
   Income = 1,
   Expense = 2,
   Discretionary = 4,
   Critical = 8
}

[Flags]
public enum MyEnum {
   Income = MyEnumReserved.Income,
   DiscretionaryExpense = MyEnumReserved.Expense | MyEnumReserved.Discretionary,
   CriticalExpense = MyEnumReserved.Expense | MyEnumReserved.Critical
}

bool IsIncome(MyEnum val) => val.HasFlag(MyEnumReserved.Income);

...
MyEnum foo = (MyEnum)MyEnumReserved.Expense | (MyEnum)MyEnumReserved.Discretionary;