接口/基类中的 C# 枚举?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1031620/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
C# enum in interface/base class?
提问by kaem
i have problem with enum
我有枚举问题
I need make a enum in base class or interface (but empty one)
我需要在基类或接口中创建一个枚举(但为空)
class Base
{
public enum Test;
// ???
}
and after make diffrent enums in some parent classes
在某些父类中进行不同的枚举之后
class Parent1
{
public enum Test {A, B, C};
}
class Parent2
{
public enum Test {J, H, K};
}
and now i have next class with method when i have to use enum
现在当我必须使用枚举时,我有了下一个带有方法的类
class Test<T>
{
public void Foo(Test enum)
{
int value = (int) enum;
// ...
}
}
It's there any way to do something like that ?
有没有办法做这样的事情?
If not i have to use static ints in every class ...
如果不是,我必须在每个类中使用静态整数......
class Parent1
{
public static int A = 0;
public static int B = 5;
public static int C = 7;
}
class Parent2
{
public static int J = 1;
public static int H = 3;
public static int K = 6;
}
class Test<T>
{
public void Foo(int enum)
{
int value = enum;
// ...
}
}
I't looks bad in code ... in some classes i have to use ~20+ variables
我的代码看起来不错……在某些课程中,我必须使用~20+ 个变量
采纳答案by Marc Gravell
There is no such thing as an abstract enum (that can have different implementations in subclasses) - but generics may be an option:
没有抽象枚举(在子类中可以有不同的实现)这样的东西 - 但泛型可能是一种选择:
class Base<T> where T : struct {
private T value;
public void Foo(T value) {
this.value = value;
}
}
class Parent1 : Base<Parent1.Enum1> {
public enum Enum1 {A, B, C};
}
class Parent2 : Base<Parent2.Enum2> {
public enum Enum2 { J, H, K };
}
The only problem is that this doesn't enforce that only enums are usable - you can do this at runtime, though - for example in a type initializer:
唯一的问题是,这并没有强制要求只有枚举可用——不过,您可以在运行时执行此操作——例如在类型初始值设定项中:
static Base() {
if (!typeof(T).IsEnum) throw new InvalidOperationException(
typeof(T).Name + " is not an enum");
}
回答by Jon Grant
No, there is no way to enforce anything static in an interface.
不,没有办法在接口中强制执行任何静态。
Perhaps you need to rethink your design.
也许您需要重新考虑您的设计。
回答by Hemant
Why cant you define the enum in base class:
为什么不能在基类中定义枚举:
class Base
{
public enum Test {A, B, C, J, H, K};
}
And use only the relevant members of enum in derived classes?
并且只在派生类中使用 enum 的相关成员?
回答by Groo
No, it can't be done.
不,这是做不到的。
Note that many enums often indicate a problem with design (many switch constructs, for example). Check this link to see an example of how to refactor this: Replace conditional with polymorphism.
请注意,许多枚举通常表示设计存在问题(例如,许多开关构造)。检查此链接以查看如何重构的示例:用多态替换条件。
回答by James
You should be able to declare an enum in a base class and then change the values per derived class i.e.
您应该能够在基类中声明一个枚举,然后更改每个派生类的值,即
class MyClass
{
public enum TestEnum { }
public MyClass()
{
}
}
class MyDerivedClass
{
public enum TestEnum { value1, value2, value3 }
public MyDerivedClass()
{
}
}
MyDervied class would have access to TestEnum.value1, TestEnum.value2, TestEnum.value3, where as MyClass would only have access to the type.
MyDervied 类可以访问 TestEnum.value1、TestEnum.value2、TestEnum.value3,而 MyClass 只能访问类型。
However, personally I don't see the advantage of doing this I would declare ALL the values of the enum in the base class and only use the ones I need per class.
但是,就我个人而言,我没有看到这样做的好处,我会在基类中声明枚举的所有值,并且只使用每个类需要的值。
James.
詹姆士。
回答by Rachel
It's amazing how often I find people arguing about whysomething is required, rather than answering the question asked or keeping schtum - either of which would be more helpful than wasting time questioning whya given enquiry has been made in preference to a different enquiry the respondent actually knows the answer to. Answering questions that have not been asked is in no way helpful, OK guys?!
令人惊讶的是,我发现人们经常争论为什么需要某些东西,而不是回答所提出的问题或保留 schtum - 这两者都比浪费时间质疑为什么进行特定查询而不是响应者的不同查询更有帮助其实知道答案。回答没有被问到的问题是没有任何帮助的,好吗伙计们?!
Getting back to the topic at hand, I've hit exactly the above scenario this morning, and can understand why it would be useful to be able to define an Enum in an interface or base class, then re-define that same-named Enum in a class that derives from either the base or interface. One use for such a design is in object-relational mapping and control binding. You might have a set of Enums that describe which Properties of your derived classes are bindable to which types of Control, such as:
回到手头的话题,今天早上我正好遇到了上面的场景,并且可以理解为什么能够在接口或基类中定义 Enum 是有用的,然后重新定义同名的 Enum在派生自基类或接口的类中。这种设计的一种用途是用于对象关系映射和控件绑定。您可能有一组枚举来描述派生类的哪些属性可绑定到哪些类型的 Control,例如:
public enum WebControlTextBoxProperties { }
public enum WebControlLabelProperties { }
...and so on.
...等等。
Since you don't know exactly which Properties will exist for a given derived class until the pertinent inheritance takes effect, but since you may also wish to have consistent Methods that consume the above Enums in your base or interface, it's a perfectly-valid design to expect to be able to define that the Enum will existin the base/interface, but define exactly what membersit has in a specific context in any derived classes.
由于在相关继承生效之前您并不确切知道给定派生类将存在哪些属性,但由于您可能还希望在基类或接口中使用一致的方法来使用上述枚举,因此这是一个完全有效的设计希望能够定义 Enum将存在于基/接口中,但在任何派生类的特定上下文中准确定义它具有哪些成员。
I really wish this were possible in C# as it is in VB, because it'd be a really useful feature.
我真的希望这在 C# 中成为可能,就像在 VB 中一样,因为这将是一个非常有用的功能。
回答by KitKat
I am at work so cannot elaborate fully, but this is possible to a point. The downside to the code below is you cannot chain enums together, such as TextBoxProperties, and MyCustomTextBoxProperties : TextboxProperties
我在工作,所以无法详细说明,但这在一定程度上是可能的。下面代码的缺点是您不能将枚举链接在一起,例如 TextBoxProperties 和 MyCustomTextBoxProperties : TextboxProperties
Here is the code.
这是代码。
public enum Test
{
}
public enum ThisTest
{
MyVal1,
MyVal2,
MyVal3
}
public abstract class MyBase
{
public Test MyEnum { get; set; }
}
public class MyDerived : MyBase
{
public new ThisTest MyEnum { get; set; }
}
回答by Simon Bridge
YOU CANABSTRACT AN ENUM!
YOU CAN摘要枚举!
Why do people insist on claiming things are impossible without checking anything?
为什么人们不检查任何东西就坚持声称事情是不可能的?
Sure, the .NET documentation is a little vague on this, but the System.Enum class, IS the abstraction of an enum. You can use System.Enum as a variable that will ONLY accept enumeration values, and you can access the name or value-type value of the enumeration through this class.
当然,.NET 文档对此有点含糊,但 System.Enum 类是枚举的抽象。您可以将 System.Enum 用作仅接受枚举值的变量,并且您可以通过此类访问枚举的名称或值类型值。
For example:
例如:
// abstracted enumeration value
Enum abstractEnum = null;
// set to the Console-Color enumeration value "Blue";
abstractEnum = System.ConsoleColor.Blue;
// the defined value of "ConsoleColor.Blue" is "9":
// you can get the value via the ToObject method:
Console.WriteLine((int)Enum.ToObject(abstractEnum.GetType(), abstractEnum));
// or via the GetHashCode() method:
Console.WriteLine(abstractEnum.GetHashCode());
// the name can also be acessed:
Console.WriteLine(Enum.GetName(abstractEnum.GetType(), abstractEnum));
The output from the above code:
上述代码的输出:
9
9
9
9
Blue
蓝色
回答by tom_p_zh
I like the accepted answer of @Marc Gravell. As i am a stackoverflow-newbie i am not allowed to comment. But i would like to add, that it is useful to also check the underlying Type of the enum - especially if you use the Flag Attribute and preform bit-wise flag-Testing operations...
我喜欢@Marc Gravell 的公认答案。由于我是一个 stackoverflow 新手,我不允许发表评论。但我想补充一点,检查枚举的基础类型也很有用 - 特别是如果您使用标志属性并执行按位标志测试操作...
if ( !typeof(T).IsEnum || typeof(int) != Enum.GetUnderlyingType(typeof(T)) )
{
throw new InvalidOperationException( typeof(T).Name + " is not an enum");
}
回答by seguso
Here's a solution that works for me:
这是一个对我有用的解决方案:
in the parent class, declare the field as int, not as enum:
在父类中,将字段声明为 int,而不是枚举:
protected int state;
so the parent class can still use this value as an int, in order to provide serialization and deserializion of this value to disk.
因此父类仍然可以将此值用作 int,以便将此值的序列化和反序列化提供给磁盘。
Then, who overrides the class can do this:
然后,覆盖该类的人可以这样做:
enum states{
state1, state2
}
this.state = state1.toInt();
and can access the actual value like this:
并且可以像这样访问实际值:
...
if (this.state == states.state1.toInt()){
...
}
else{
...
}
where toInt() is defined in a static class as follows:
其中 toInt() 在静态类中定义如下:
public static class Utils
{
public static int toInt(this state s)
{
return (int)s;
}
}