首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >C# enum型安全

C# enum型安全
EN

Stack Overflow用户
提问于 2015-09-05 23:35:46
回答 2查看 2K关注 0票数 5

是否有一种方法强迫C#枚举只接受几个显式命名常量中的一个,还是有另一个特性可以接受?C#引用有这样的事后考虑:

可以将任意整数值赋值给枚举类型。但是,您不应该这样做,因为隐含的期望是枚举变量将只保存枚举定义的一个值。将任意值赋值给枚举类型的变量将带来错误的高风险。

(设计了一种新的语言,允许这种草率。)这让我很困惑。)

EN

回答 2

Stack Overflow用户

发布于 2015-09-06 00:05:21

据我所知,您无法阻止C#允许在枚举和整数之间进行转换。

作为解决办法,您可以使用带有受限实例化的自定义类型。用法将类似,但您也将有机会为这种类型定义方法和运算符。

就说你有这件事:

代码语言:javascript
复制
enum DayOfWeek
{
    Monday, Tuesday, Wednesday, Thursday, Friday, Saturday, Sunday 
}

你可以用一个密封的类代替它。优点是免费获得比较(因为在这种情况下,值比较和引用比较是等价的)。缺点是(与C#中的所有引用类型一样),它是可空的。

代码语言:javascript
复制
sealed class DayOfWeek
{
    public static readonly DayOfWeek Monday = new DayOfWeek(0);
    public static readonly DayOfWeek Tuesday = new DayOfWeek(1);
    public static readonly DayOfWeek Wednesday = new DayOfWeek(2);
    public static readonly DayOfWeek Thursday = new DayOfWeek(3);
    public static readonly DayOfWeek Friday = new DayOfWeek(4);
    public static readonly DayOfWeek Saturday = new DayOfWeek(5);
    public static readonly DayOfWeek Sunday = new DayOfWeek(6);

    private readonly int _value;

    private DayOfWeek(int value) 
    {
        _value = value;
    }
}

或者你可以用一个结构。它的优点是它不能为空,因此它甚至更类似于枚举。缺点是您必须手动实现比较代码:

代码语言:javascript
复制
struct DayOfWeek
{
    public static readonly DayOfWeek Monday = new DayOfWeek(0);
    public static readonly DayOfWeek Tuesday = new DayOfWeek(1);
    public static readonly DayOfWeek Wednesday = new DayOfWeek(2);
    public static readonly DayOfWeek Thursday = new DayOfWeek(3);
    public static readonly DayOfWeek Friday = new DayOfWeek(4);
    public static readonly DayOfWeek Saturday = new DayOfWeek(5);
    public static readonly DayOfWeek Sunday = new DayOfWeek(6);

    private readonly int _value;

    private DayOfWeek(int value)
    {
        _value = value;
    }

    public bool Equals(DayOfWeek other)
    {
        return _value == other._value;
    }

    public override bool Equals(object obj)
    {
        if (ReferenceEquals(null, obj))
        {
            return false;
        }
        return obj is DayOfWeek && Equals((DayOfWeek)obj);
    }

    public override int GetHashCode()
    {
        return _value;
    }

    public static bool operator ==(DayOfWeek op1, DayOfWeek op2)
    {
        return op1.Equals(op2);
    }

    public static bool operator !=(DayOfWeek op1, DayOfWeek op2)
    {
        return !(op1 == op2);
    }
}
票数 4
EN

Stack Overflow用户

发布于 2015-09-06 00:02:35

将任何整数强制转换为枚举的能力主要是由于性能原因,但作为值类型实现的枚举不能保护其不包含未定义的值。考虑一种类似于:

代码语言:javascript
复制
public enum Condition {
  Right = 1,
  Wrong = 2
}

即使枚举变量的赋值仅限于定义的值,您仍然可以通过简单地将其放入类中来创建未定义的值:

代码语言:javascript
复制
public class Demo {
  public Condition Cond;
}

当创建类的实例时,成员被初始化为零,因此Cond成员变量将具有未定义的(Condition)0值。

您可以创建一个包装类,以确保枚举值在定义的值中:

代码语言:javascript
复制
public sealed class SafeEnum<T> where T : struct {

  public T Value { get; private set; }

  public SafeEnum(T value) {
    if (!(value is Enum)) {
      throw new ArgumentException("The type is not an enumeration.");
    }
    if (!Enum.IsDefined(typeof(T), value)) {
      throw new ArgumentException("The value is not defined in the enumeration.");
    }
    Value = value;
  }

}

示例:

代码语言:javascript
复制
var cond = new SafeEnum<Condition>(Condition.Right); // works
Condition d = cond.Value;

var cond = new SafeEnum<int>(42); // not an enum

var cond = new SafeEnum<Condition>((Condition)42); // not defined

类的实例只能包含在枚举中定义的值,否则构造函数将不允许创建实例。

由于类是不可变的,因此值不能更改为未定义的值。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/32418634

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档