C# 中隐藏的枚举值

发布于 2024-09-16 12:30:47 字数 204 浏览 5 评论 0原文

我有一个枚举,我想“隐藏”它的一个值(因为我添加它是为了将来的支持)。 该代码是用 C# 编写的。

public enum MyEnum
{
   ValueA = 0,

   ValueB = 1,

   Reserved
}

我不想允许使用此代码的人使用此值(MyEnum.Reserved)。 有什么想法吗? TIA

I have an enum and i want to "hide" one of its values (as i add it for future support).
The code is written in C#.

public enum MyEnum
{
   ValueA = 0,

   ValueB = 1,

   Reserved
}

I don't want to allow peoples who use this code to use this values (MyEnum.Reserved).
Any idea?
TIA

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(9

背叛残局 2024-09-23 12:30:47

您可以使用“Obsolete”属性 - 语义上不正确,但它会执行您想要的操作:

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

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

You could use the 'Obsolete' attribute - semantically incorrect, but it will do what you want:

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

Anyone who tries to compile using the Foo.Reserved item will get an error

回心转意 2024-09-23 12:30:47

如果您不想显示它,则不要包含它:

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

    // ...
}

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

If you don't want to show it, then don't include it:

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

Note that a user of this enum can still assign any integer value to a variable declared as MyEnum:

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

This means that a method that accepts an enum should always validate this input before using it:

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

    // ...
}

So, just add your value later, when you need it, and modify your methods to accept it then.

心在旅行 2024-09-23 12:30:47

这在 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!

This is not possible in C#. All enum values are accessible if the Enum itself is accessible.

The only way you could simulate accomplishing this is by using a less accessible static field that used an integer value not already used in the Enum.

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

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

I'm curious though as to why you would want to do this. No matter what you do users can still provide the Reserved value. All that needs to be done is to cast an int of the appropriate value to the MyEnum type.

// Code that shouldn't access Reserve
MyEnum reserved = (MyEnum)42;  // Woot!
轮廓§ 2024-09-23 12:30:47

如果要隐藏智能感知或 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 不可见

if you want to hide from intellisense or PropertyGrid enumerated members, you can apply:

[System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]

and

[System.ComponentModel.Browsable(false)]

Example:

  public enum MyEnum
  {
     A,

     B,
     [System.ComponentModel.Browsable(false)]
     [System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]
     C
  }

C is not visible

痴意少年 2024-09-23 12:30:47

您可以通过使用自己的自定义类型而不是枚举来实现类似的效果:

// 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");
}

您甚至可以通过以下方式进一步模拟枚举值的行为 :例如,重载 explicit 运算符以将 MyEnum 对象转换为 int 值(采纳 JaredPar 的建议,使用此运算符而不是 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;
}

You can achieve something like this by using your own custom type instead of 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");
}

You could even further emulate the behavior of enum values by, for example, overloading the explicit operators to convert to/from MyEnum objects to int values (took JaredPar's suggestion to use this rather than 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;
}
薄荷→糖丶微凉 2024-09-23 12:30:47

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

您可以创建两种枚举类型,一种用于保留值,另一种用于公共可用值。您可以将 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;

I had a similar problem with enum Flags, but the solution I used should work without the Flags attribute.

You can create two enum types, one for the reserved values and the other for the publicly usable values. You can use HasFlag with the reserved type without casting, but assignment requires casting.

[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;
番薯 2024-09-23 12:30:47

您无法隐藏它,但您可以添加注释,表明该值目前没有任何作用。否则,只需删除它并在添加支持时添加它,只要原始值不改变,这就不应该破坏依赖于它的任何其他代码。

You can't hide it, but you can add a comment that this value doesn't have any effect at this moment. Otherwise just remove it and add it if you add the support, this shouldn't break any other code dependent on it, as long as the original values don't change.

赠意 2024-09-23 12:30:47

您在内部使用“隐藏”值吗?如果不是:

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

定义未使用的变量不会带来任何好处。

Are you using the "hidden" value internally? If not:

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

You gain nothing by defining an unused variable.

娇俏 2024-09-23 12:30:47

实现此目的的一种方法是设置此变量 null 的值。
因此,当从 enum 调用它时,它将为 null。简而言之用户无法访问它的值。

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

   Reserved.None
}

one way you can do this set the value of this variable null.
so when ever its called from enum it'll b null. in short user can't access its value.

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

   Reserved.None
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文