enum Fruit
{
Banana,
Orange,
Strawberry
...
...
// etc, very long enum
}
PeelFruit(Fruit.Orange);
PeelFruit(Fruit.Banana);
PeelFruit(Fruit.Strawberry); // huh? can't peel strawberries!
抱歉这个蹩脚的例子,但希望你能得到这个想法。有没有办法约束PeelFruit
将接受的枚举值?
很明显我可以使用开关或其他东西在方法中检查它们,但是如果有办法这样做会很酷a)更紧凑一些,并且b)会导致编译时错误,而不是运行时错误。
[Fruit = Orange,Bannana]
void PeelFruit(Fruit fruit) { ... }
答案 0 :(得分:7)
这对于基本语言功能是不可能的(虽然code contracts可以使用compile-time checking is only available with the premium edition。实际上,您甚至无法将输入限制在enum
中定义的值!接受Fruit
参数的方法将接受任何int
(或枚举的类型,如果它不是整数),只要调用者首先将其转换为Fruit
:
PeelFruit((Fruit)10000); // Not a Fruit? Not a problem!
答案 1 :(得分:3)
从你的例子中不清楚你真正想要做什么。你不能像你建议的那样对枚举有约束,因为枚举的所有值都是等价的并且是相同的类型。编译器只关心类型,而不关心值,因此它无法区分。
如果由于某些特殊原因不需要枚举,那么你可以实现相同的一种方法就是使用类型系统。而不是枚举,定义一个对象层次。如果你愿意,物品本身可以是单独的占位符。这样您就可以使用类型系统来执行此操作。作为一个例子
public abstract class Fruit { protected PeelableFruit() { } };
public abstract class PeelableFruit : Fruit { protected PeelableFruit() { } };
public class Orange : PeelableFruit { public static readonly Instance = new Orange(); protected Orange() { } };
etc. etc.
void AcceptsAnyFruit(Fruit ....) { }
void AcceptsPeelableFruit(PeelableFruit ....) { }
有意义吗?
答案 2 :(得分:1)
您可以使用code contracts进行编译器检查。我相信你可以这样做:
Contract.Requires(fruit != Fruit.Strawberry)
答案 3 :(得分:1)
可能的方法是使用对象来代表水果,而不是使用枚举。这将使您能够进行编译时检查。
每个水果类都会实现接口来说明他们允许或不允许的内容。
而不是
void PeelFruit(Fruit fruit) { ... }
它将是
void PeelFruit(IPeelable fruit) { ... }
答案 4 :(得分:0)
一个非常简单的方法是在示例中分配数值
enum Fruit
{
Banana = 1,
Orange = 2,
Strawberry = 4
...
...
// etc, very long enum
}
然后检查
if ((int) thefruit > 2)
...
else
...
答案 5 :(得分:0)
有2个枚举,一个用于可剥离的水果,一个用于不可剥离的水果?如果枚举不适用于所有情况,那么无论如何它们应该是分开的东西。
这可能更好地解决了使用带有fruit,peelableFruit等实例的类型层次结构,它会强制编译器进行类型检查,这无论如何都不会真正在Enum上完成,正如已经指出的那样。
您可以使用没有功能的Marker接口来识别类型并允许它们传递给方法。
答案 6 :(得分:0)
你提出的是一个属性,它是一个运行时实体,而不是编译时间。没有办法做你提出的建议,但你真的要问自己设计是否正确。如果你控制了枚举,可能有两个单独的枚举会更有意义。与PeelableFruit
和NonPeelableFruit
一样。
答案 7 :(得分:0)
如果你想要编译时检查,那么我担心你不得不去上课。
如果你满足于运行时检查,那么最紧凑的形式将是一个检查值的函数。
void PeelFruit(Fruit fruit)
{
if (!Peelable(fruit))
throw new ArgumentException("Fruit is nonpeelable.");
...
}
static bool Peelable(Fruit fruit) { ... }
如果您希望调用者能够验证他们没有传递错误的值,请将其设为公共函数。然后他们将不必处理异常。