[英]Enum value as hidden in C#
我有一个枚举,我想“隐藏”它的一个值(因为我添加了它以供将来支持)。 代码是用 C# 编写的。
public enum MyEnum
{
ValueA = 0,
ValueB = 1,
Reserved
}
我不想让使用此代码的人使用此值 (MyEnum.Reserved)。 任何的想法? TIA
您可以使用 'Obsolete' 属性 - 语义上不正确,但它会做你想做的事:
public enum MyEnum
{
ValueA = 0,
ValueB = 1,
[Obsolete("Do not use this", true)]
Reserved
}
任何尝试使用Foo.Reserved
项进行编译的Foo.Reserved
都会收到错误消息
如果您不想显示它,请不要包含它:
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();
}
// ...
}
因此,只需稍后在需要时添加您的值,然后修改您的方法以接受它。
这在 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!
如果你想隐藏 intellisense 或 PropertyGrid 枚举成员,你可以申请:
[System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]
和
[System.ComponentModel.Browsable(false)]
例子:
public enum MyEnum
{
A,
B,
[System.ComponentModel.Browsable(false)]
[System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]
C
}
C 不可见
您可以通过使用自己的自定义类型而不是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
对象转换为/从MyEnum
对象转换为int
值(采用 JaredPar 的建议使用 this 而不是implicit
):
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;
}
您是否在内部使用“隐藏”值? 如果不:
public enum MyEnum
{
ValueA = 0,
ValueB = 1,
//TODO: Reserved
}
定义一个未使用的变量你一无所获。
一种方法可以设置此变量的null
。 所以当它从enum
调用时,它会为空。 简而言之,用户无法访问其值。
public enum MyEnum
{
ValueA = 0,
ValueB = 1,
Reserved.None
}
你不能隐藏它,但你可以添加一个注释,这个值此时没有任何影响。 否则只需删除它并在添加支持时添加它,只要原始值不更改,这不应破坏任何其他依赖于它的代码。
我对 enum 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;
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.