有没有办法强制C#枚举只接受几个明确命名的常量之一,或者是否有另一个功能呢? C#参考有这个后缀:C#枚举类型安全
可以将任意的整数值赋给一个枚举类型。 但是,您不应该这样做,因为隐式期望是 enum变量将仅保存由 枚举定义的值之一。将任意值分配给枚举类型的变量 类型将导致错误的高风险。
(一种新的语言的设计,让这种草率的,这是莫名其妙的给我。)
有没有办法强制C#枚举只接受几个明确命名的常量之一,或者是否有另一个功能呢? C#参考有这个后缀:C#枚举类型安全
可以将任意的整数值赋给一个枚举类型。 但是,您不应该这样做,因为隐式期望是 enum变量将仅保存由 枚举定义的值之一。将任意值分配给枚举类型的变量 类型将导致错误的高风险。
(一种新的语言的设计,让这种草率的,这是莫名其妙的给我。)
投一个枚举的任意整数的能力是主要是因为性能的原因,但实现的枚举作为一个值类型根本无法保护包含未定义的值。考虑一个枚举,如:
public enum Condition {
Right = 1,
Wrong = 2
}
即使分配到一个枚举变量被限制为只定义的值,您仍然可以通过简单地把它在一个类中创建一个未定义的值:
public class Demo {
public Condition Cond;
}
当你创建类的实例,成员初始化为零,因此Cond
成员变量将具有未定义的值(Condition)0
。
你可以让一个包装类,以确保枚举值定义的值中:
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;
}
}
例子:
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
的类的实例只能包含一个值,在枚举中定义,否则构造函数将不允许创建实例。
由于该类是不可变的,因此该值不能更改为未定义的值。
据我所知,你不能阻止C#允许在枚举和整数之间转换。
作为一种变通方法,你也可以使用受限制的实例化自定义类型。用法看起来很相似,但您也有机会定义此类型的方法和运算符。
说你有这样的枚举:
enum DayOfWeek
{
Monday, Tuesday, Wednesday, Thursday, Friday, Saturday, Sunday
}
你可以在它的位置使用密封类。好处是您可以免费进行比较(因为在这种情况下,值比较和参考比较是相同的)。缺点是(像C#中的所有引用类型一样),它是可空的。
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;
}
}
或者你可以使用一个结构。优点是它不是空的,因此它更像一个枚举。缺点是你必须手动实现比较代码:
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);
}
}
有一件事情会让事情变得更糟 - 现在你可以将'null'分配给'DayOfWeek',因为它是一个类。 – MarcinJuraszek
@MarcinJuraszek你是对的。我已经包含了一种替代方法。 –
'struct'方法给出了另一个问题 - 您可以通过调用无过于构造函数来创建附加值。无论如何,编译器都会为每个结构体默认定义它。 – MarcinJuraszek