C# 枚举“继承”
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/757684/
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
Enum "Inheritance"
提问by CodeMonkey1313
I have an enum in a low level namespace. I'd like to provide a class or enum in a mid level namespace that "inherits" the low level enum.
我在低级命名空间中有一个枚举。我想在“继承”低级枚举的中级命名空间中提供一个类或枚举。
namespace low
{
public enum base
{
x, y, z
}
}
namespace mid
{
public enum consume : low.base
{
}
}
I'm hoping that this is possible, or perhaps some kind of class that can take the place of the enum consume which will provide a layer of abstraction for the enum, but still let an instance of that class access the enum.
我希望这是可能的,或者可能是某种可以代替枚举消耗的类,它将为枚举提供一个抽象层,但仍然让该类的实例访问枚举。
Thoughts?
想法?
EDIT: One of the reasons I haven't just switched this to consts in classes is that the low level enum is needed by a service that I must consume. I have been given the WSDLs and the XSDs, which define the structure as an enum. The service cannot be changed.
编辑:我没有在类中将其切换为 consts 的原因之一是我必须使用的服务需要低级枚举。我得到了 WSDL 和 XSD,它们将结构定义为枚举。服务无法更改。
采纳答案by JaredPar
This is not possible. Enums cannot inherit from other enums. In fact all enums must actually inherit from System.Enum
. C# allows syntax to change the underlying representation of the enum values which looks like inheritance, but in actuality they still inherit from System.enum.
这不可能。枚举不能从其他枚举继承。事实上,所有枚举都必须真正继承自System.Enum
. C# 允许语法更改枚举值的底层表示,这看起来像继承,但实际上它们仍然从 System.enum 继承。
See section 8.5.2 of the CLI specfor the full details. Relevant information from the spec
有关完整详细信息,请参阅CLI 规范的第 8.5.2 节。规范中的相关信息
- All enums must derive from
System.Enum
- Because of the above, all enums are value types and hence sealed
- 所有枚举必须来自
System.Enum
- 由于上述原因,所有枚举都是值类型,因此是密封的
回答by Brian Genisio
The short answer is no. You can play a bit, if you want:
最简洁的答案是不。如果你愿意,你可以玩一点:
You can always do something like this:
你总是可以做这样的事情:
private enum Base
{
A,
B,
C
}
private enum Consume
{
A = Base.A,
B = Base.B,
C = Base.C,
D,
E
}
But, it doesn't work all that great because Base.A != Consume.A
但是,它并没有那么好用,因为 Base.A != Consume.A
You can always do something like this, though:
不过,您始终可以执行以下操作:
public static class Extensions
{
public static T As<T>(this Consume c) where T : struct
{
return (T)System.Enum.Parse(typeof(T), c.ToString(), false);
}
}
In order to cross between Base and Consume...
为了在 Base 和 Consume 之间进行交叉......
You could also cast the values of the enums as ints, and compare them as ints instead of enum, but that kind of sucks too.
您也可以将枚举的值转换为整数,并将它们作为整数而不是枚举进行比较,但这也很糟糕。
The extension method return should type cast it type T.
扩展方法返回应该将其类型转换为 T。
回答by Lucero
Enums are not actual classes, even if they look like it. Internally, they are treated just like their underlying type (by default Int32). Therefore, you can only do this by "copying" single values from one enum to another and casting them to their integer number to compare them for equality.
枚举并不是真正的类,即使它们看起来很像。在内部,它们被视为它们的底层类型(默认为 Int32)。因此,您只能通过将单个值从一个枚举“复制”到另一个枚举并将它们转换为整数以比较它们的相等性来做到这一点。
回答by Pascal
Ignoring the fact that base is a reserved word you cannot do inheritance of enum.
忽略 base 是保留字的事实,您不能继承枚举。
The best thing you could do is something like that:
你能做的最好的事情是这样的:
public enum Baseenum
{
x, y, z
}
public enum Consume
{
x = Baseenum.x,
y = Baseenum.y,
z = Baseenum.z
}
public void Test()
{
Baseenum a = Baseenum.x;
Consume newA = (Consume) a;
if ((Int32) a == (Int32) newA)
{
MessageBox.Show(newA.ToString());
}
}
Since they're all the same base type (ie: int) you could assign the value from an instance of one type to the other which a cast. Not ideal but it work.
由于它们都是相同的基本类型(即:int),您可以将一种类型的实例的值分配给另一种类型的实例。不理想,但它有效。
回答by Jeroen Landheer
Enums cannot be derrived from other enums, but only from int, uint, short, ushort, long, ulong, byte and sbyte.
枚举不能从其他枚举派生,而只能从 int、uint、short、ushort、long、ulong、byte 和 sbyte 派生。
Like Pascal said, you can use other enum's values or constants to initialize an enum value, but that's about it.
就像 Pascal 所说的那样,您可以使用其他枚举的值或常量来初始化枚举值,但仅此而已。
回答by M4N
You can achieve what you want with classes:
你可以通过类来实现你想要的:
public class Base
{
public const int A = 1;
public const int B = 2;
public const int C = 3;
}
public class Consume : Base
{
public const int D = 4;
public const int E = 5;
}
Now you can use these classes similar as when they were enums:
现在您可以像使用枚举一样使用这些类:
int i = Consume.B;
Update(after your update of the question):
更新(在您更新问题之后):
If you assign the same int values to the constants as defined in the existing enum, then you can cast between the enum and the constants, e.g:
如果为现有枚举中定义的常量分配相同的 int 值,则可以在枚举和常量之间进行转换,例如:
public enum SomeEnum // this is the existing enum (from WSDL)
{
A = 1,
B = 2,
...
}
public class Base
{
public const int A = (int)SomeEnum.A;
//...
}
public class Consume : Base
{
public const int D = 4;
public const int E = 5;
}
// where you have to use the enum, use a cast:
SomeEnum e = (SomeEnum)Consume.B;
回答by Seven
The solutions above using classes with int constants lack type-safety. I.e. you could invent new values actually not defined in the class. Furthermore it is not possible for example to write a method taking one of these classes as input.
上面使用带有 int 常量的类的解决方案缺乏类型安全性。即您可以发明实际上未在类中定义的新值。此外,不可能例如编写以这些类中的一个作为输入的方法。
You would need to write
你需要写
public void DoSomethingMeaningFull(int consumeValue) ...
However, there is a class based solution of the old days of Java, when there were no enums available. This provides an almost enum-like behaviour. The only caveat is that these constants cannot be used within a switch-statement.
但是,当没有可用的枚举时,Java 的旧时代有一个基于类的解决方案。这提供了几乎类似于枚举的行为。唯一需要注意的是,这些常量不能在 switch 语句中使用。
public class MyBaseEnum
{
public static readonly MyBaseEnum A = new MyBaseEnum( 1 );
public static readonly MyBaseEnum B = new MyBaseEnum( 2 );
public static readonly MyBaseEnum C = new MyBaseEnum( 3 );
public int InternalValue { get; protected set; }
protected MyBaseEnum( int internalValue )
{
this.InternalValue = internalValue;
}
}
public class MyEnum : MyBaseEnum
{
public static readonly MyEnum D = new MyEnum( 4 );
public static readonly MyEnum E = new MyEnum( 5 );
protected MyEnum( int internalValue ) : base( internalValue )
{
// Nothing
}
}
[TestMethod]
public void EnumTest()
{
this.DoSomethingMeaningful( MyEnum.A );
}
private void DoSomethingMeaningful( MyBaseEnum enumValue )
{
// ...
if( enumValue == MyEnum.A ) { /* ... */ }
else if (enumValue == MyEnum.B) { /* ... */ }
// ...
}
回答by Sriwantha Attanayake
You can perform inheritance in enum, however it's limited to following types only . int, uint, byte, sbyte, short, ushort, long, ulong
您可以在 enum 中执行继承,但仅限于以下类型。int, uint, byte, sbyte, short, ushort, long, ulong
E.g.
例如
public enum Car:int{
Toyota,
Benz,
}
回答by Tono Nam
I know this answer is kind of late but this is what I ended up doing:
我知道这个答案有点晚了,但这就是我最终要做的:
public class BaseAnimal : IEquatable<BaseAnimal>
{
public string Name { private set; get; }
public int Value { private set; get; }
public BaseAnimal(int value, String name)
{
this.Name = name;
this.Value = value;
}
public override String ToString()
{
return Name;
}
public bool Equals(BaseAnimal other)
{
return other.Name == this.Name && other.Value == this.Value;
}
}
public class AnimalType : BaseAnimal
{
public static readonly BaseAnimal Invertebrate = new BaseAnimal(1, "Invertebrate");
public static readonly BaseAnimal Amphibians = new BaseAnimal(2, "Amphibians");
// etc
}
public class DogType : AnimalType
{
public static readonly BaseAnimal Golden_Retriever = new BaseAnimal(3, "Golden_Retriever");
public static readonly BaseAnimal Great_Dane = new BaseAnimal(4, "Great_Dane");
// etc
}
Then I am able to do things like:
然后我可以做这样的事情:
public void SomeMethod()
{
var a = AnimalType.Amphibians;
var b = AnimalType.Amphibians;
if (a == b)
{
// should be equal
}
// call method as
Foo(a);
// using ifs
if (a == AnimalType.Amphibians)
{
}
else if (a == AnimalType.Invertebrate)
{
}
else if (a == DogType.Golden_Retriever)
{
}
// etc
}
public void Foo(BaseAnimal typeOfAnimal)
{
}
回答by ShloEmi
another possible solution:
另一种可能的解决方案:
public enum @base
{
x,
y,
z
}
public enum consume
{
x = @base.x,
y = @base.y,
z = @base.z,
a,b,c
}
// TODO: Add a unit-test to check that if @base and consume are aligned
HTH
HTH