简体   繁体   English

枚举值隐藏在 C# 中

[英]Enum value as hidden in C#

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#.代码是用 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).我不想让使用此代码的人使用此值 (MyEnum.Reserved)。 Any idea?任何的想法? TIA TIA

You could use the 'Obsolete' attribute - semantically incorrect, but it will do what you want:您可以使用 'Obsolete' 属性 - 语义上不正确,但它会做你想做的事:

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任何尝试使用Foo.Reserved项进行编译的Foo.Reserved都会收到错误消息

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 的变量:

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.因此,只需稍后在需要时添加您的值,然后修改您的方法以接受它。

This is not possible in C#.这在 C# 中是不可能的。 All enum values are accessible if the Enum itself is accessible.如果Enum本身可访问,则所有枚举值均可访问。

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 .您可以模拟完成此操作的唯一方法是使用一个不太容易访问的静态字段,该字段使用了一个尚未在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.无论您做什么,用户仍然可以提供Reserved值。 All that needs to be done is to cast an int of the appropriate value to the MyEnum type.需要做的就是将适当值的int转换为MyEnum类型。

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

if you want to hide from intellisense or PropertyGrid enumerated members, you can apply:如果你想隐藏 intellisense 或 PropertyGrid 枚举成员,你可以申请:

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

and

[System.ComponentModel.Browsable(false)] [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 C 不可见

You can achieve something like this by using your own custom type instead of enum :您可以通过使用自己的自定义类型而不是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 ):您甚至可以进一步模拟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;
}

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.定义一个未使用的变量你一无所获。

one way you can do this set the value of this variable null .一种方法可以设置此变量的null so when ever its called from enum it'll b null.所以当它从enum调用时,它会为空。 in short user can't access its value.简而言之,用户无法访问其值。

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

   Reserved.None
}

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.否则只需删除它并在添加支持时添加它,只要原始值不更改,这不应破坏任何其他依赖于它的代码。

I had a similar problem with enum Flags, but the solution I used should work without the Flags attribute.我对 enum Flags 有类似的问题,但我使用的解决方案应该可以在没有 Flags 属性的情况下工作。

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.您可以在不强制转换的情况下将 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.

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