c#:用继承构建java风格的枚举
本文关键字:风格 枚举 java 构建 继承 | 更新日期: 2023-09-27 18:07:57
我希望为c#构建一个java风格的枚举模式,也支持继承。我在收益回报方面遇到了麻烦。具体来说,从child 's Values属性返回BaseEnum的值。
public class BaseEnum {
public static readonly BaseEnum A = new BaseEnum("A");
public static readonly BaseEnum B = new BaseEnum("B");
public static readonly BaseEnum C = new BaseEnum("C");
public static IEnumerable<BaseEnum> Values {
get {
yield return A;
yield return B;
yield return C;
}
}
public readonly String Name;
protected BaseEnum(String name) {
this.Name = name;
}
public static void TestMain() {
Console.WriteLine("BaseEnum, should print (A,B,C):");
foreach(BaseEnum e in BaseEnum.Values) {
Console.WriteLine(e.Name);
}
Console.WriteLine("BaseEnum in ChildEnum, should print (A,B,C,D,E):");
foreach(BaseEnum e in ChildEnum.Values) {
Console.WriteLine(e.Name);
}
Console.WriteLine("ChildEnum in ChildEnum, should print (D,E):");
foreach(ChildEnum e in ChildEnum.Values) {
Console.WriteLine(e.Name);
}
}
}
class ChildEnum : BaseEnum {
public static readonly ChildEnum D = new ChildEnum("D");
public static readonly ChildEnum E = new ChildEnum("E");
new public static IEnumerable<BaseEnum> Values {
get {
// yield return BaseEnum.Values; // This is what I want to do. It gives the error message below:
// Cannot implicitly convert type 'System.Collections.Generic.IEnumerable<Abra.Workshop.EnumABC>'
// to 'Abra.Workshop.EnumABC'. An explicit conversion exists (are you missing a cast?)
yield return D;
yield return E;
}
}
public ChildEnum(string name)
: base(name) {
}
}
/* Output!
BaseEnum, should print (A,B,C):
A
B
C
BaseEnum in ChildEnum, should print (A,B,C,D,E):
D
E
ChildEnum in ChildEnum, should print (D,E):
D
E
*/
使用
foreach (var b in BaseEnum.Values)
yield return b;
你需要打开BaseEnum。值转换为单个元素。
或者将其替换为LINQ表达式:-
return BaseEnum.Values.Concat(new[]{ D, E });
class Program
{
static void Main(string[] args)
{
Console.WriteLine("BaseEnum, should print (A,B,C):");
foreach (BaseEnum e in BaseEnum.Values)
{
Console.WriteLine(e.Name);
}
Console.WriteLine("BaseEnum in ChildEnum, should print (A,B,C,D,E):");
foreach (BaseEnum e in ChildEnum.Values)
{
Console.WriteLine(e.Name);
}
Console.WriteLine("ChildEnum in ChildEnum, should print (D,E):");
foreach (ChildEnum e in ChildEnum.Values.Where(d => d.GetType() == typeof(ChildEnum)))
{
Console.WriteLine(e.Name);
}
}
}
public class BaseEnum
{
public static readonly BaseEnum A = new BaseEnum("A");
public static readonly BaseEnum B = new BaseEnum("B");
public static readonly BaseEnum C = new BaseEnum("C");
public static IEnumerable<BaseEnum> Values
{
get
{
yield return A;
yield return B;
yield return C;
}
}
public readonly String Name;
protected BaseEnum(String name)
{
this.Name = name;
}
}
public class ChildEnum : BaseEnum
{
public static readonly ChildEnum D = new ChildEnum("D");
public static readonly ChildEnum E = new ChildEnum("E");
new public static IEnumerable<BaseEnum> Values
{
get
{
foreach (var baseEnum in BaseEnum.Values)
yield return baseEnum;
yield return D;
yield return E;
}
}
public ChildEnum(string name)
: base(name)
{
}
}
这个版本不需要使用讨厌的new public static
枚举器。
它确实改变了继承结构以使其工作。我想我应该把它作为一种选择。
public class BaseEnum<E> where E : BaseEnum<E>, new()
{
public static readonly E A = new E() { Name = "A" };
public static readonly E B = new E() { Name = "B" };
public static readonly E C = new E() { Name = "C" };
public string Name { get; protected set; }
protected static IEnumerable<E> InternalValues
{
get
{
yield return A;
yield return B;
yield return C;
}
}
}
public class BaseEnum : BaseEnum<BaseEnum>
{
public static IEnumerable<BaseEnum> Values
{
get { foreach (var x in InternalValues) yield return x; }
}
}
public class ChildEnum : BaseEnum<ChildEnum>
{
public static readonly ChildEnum D = new ChildEnum() { Name = "D" };
public static readonly ChildEnum E = new ChildEnum() { Name = "E" };
public static IEnumerable<ChildEnum> Values
{
get
{
foreach (var x in InternalValues) yield return x;
yield return D;
yield return E;
}
}
}
它也需要一个默认的公共构造函数,但是由于Name
属性上的protected setter,只有在继承层次结构中运行的代码才能设置名称,所以如果一个实例没有名称,你就知道有人做错了。