C# 标志的自定义枚举基类
我正在按照的思路创建一个自定义枚举类,但很难创建一个支持标志样式枚举的版本 当尝试按位或将两个实例合并以创建不存在的新实例时,会出现问题C# 标志的自定义枚举基类,c#,oop,.net-core,C#,Oop,.net Core,我正在按照的思路创建一个自定义枚举类,但很难创建一个支持标志样式枚举的版本 当尝试按位或将两个实例合并以创建不存在的新实例时,会出现问题 公共抽象类枚举 其中TEnum:枚举 { public int Id{get;private set;} 公共字符串名称{get;private set;} 受保护的枚举(int-id,string-name)=>(id,name)=(id,name); 公共重写字符串ToString()=>名称; 公共静态IEnumerable GetAll()=> typ
公共抽象类枚举
其中TEnum:枚举
{
public int Id{get;private set;}
公共字符串名称{get;private set;}
受保护的枚举(int-id,string-name)=>(id,name)=(id,name);
公共重写字符串ToString()=>名称;
公共静态IEnumerable GetAll()=>
typeof(T).GetFields(BindingFlags.Public | BindingFlags.Static | BindingFlags.DeclaredOnly)
.Where(info=>enumerationType.IsAssignableFrom(info.FieldType))
.Select(f=>f.GetValue(null))
.Cast();
公共静态枚举运算符|(枚举左,枚举右)
{
//这就是问题的解决方法!
//很明显,我可以按位或将这两个值合并,但是如何创建实例呢
//从这里算起,这是一个有效的名字?
//例如,Colors.Red | Colors.Blue需要是
//Id==(1问题总是无法从抽象基类内部以本机方式构造Colors
的实例。也就是说,可以将泛型约束为具有new()
,但不能具有像new(int,string)
这样的特定构造函数
因此,一种选择是在具体类本身内部定义(并为枚举的每个实例重新定义)操作符
public class Colors : Enumeration<Colors>
{
public static readonly Colors Red = new Colors(1 << 0, "Red");
public static readonly Colors Blue = new Colors(1 << 1, "Blue");
public static readonly Colors Green = new Colors(1 << 2, "Green");
public Colors(int id, string name) : base(id, name) { }
public static Colors operator |(Colors left, Colors right)
{
return new Colors(left.Id | right.Id, $"{left.Name}, {right.Name}");
}
}
公共类颜色:枚举
{
public static readonly Colors Red=new Colors(1您是否尝试过返回新的数字(left.Id | right.Id,$“{left.Name},{right.Name}”);
?问题总是在于您无法在枚举
中构造颜色
(即,上面的注释将不起作用)这将意味着对基类中的每种枚举类型都进行ex/隐式强制转换。糟糕!您可以使用反射这样做return(enumeration)Activator.CreateInstance(typeof(TEnum),left.Id | right.Id,$“{left.Name},{right.Name}”);
,但仍然需要强制转换结果(即颜色红蓝=(颜色)(Colors.Red | Colors.Blue);`.@itsme86想出了一种不用这么做的方法:)没有人会喜欢这样的回答!不幸的是,这正是我试图避免的事情——我不希望每个进行枚举的人都必须重新定义一个方法。尽管如此,我还是喜欢第二个选项,其中子类必须定义如何创建自身的实例。我不确定这是比使用Activat更好还是更糟或者。@Coda17哦,我同意第一个选项很糟糕,因此我继续思考。似乎唯一的选项是这个或使用Activator,所以将其标记为已接受。
public abstract class Enumeration<TEnum>
where TEnum : Enumeration<TEnum>
{
public int Id { get; private set; }
public string Name { get; private set; }
protected Enumeration(int id, string name) => (Id, Name) = (id, name);
public override string ToString() => Name;
public static Enumeration<TEnum> operator |(Enumeration<TEnum> left, Enumeration<TEnum> right)
{
return left.Create(left.Id | right.Id, $"{left.Name}, {right.Name}");
}
protected abstract Enumeration<TEnum> Create(int id, string name);
// Other utility methods ...
}
public class Colors : Enumeration<Colors>
{
public static readonly Colors Red = new Colors(1 << 0, "Red");
public static readonly Colors Blue = new Colors(1 << 1, "Blue");
public static readonly Colors Green = new Colors(1 << 2, "Green");
public Colors(int id, string name) : base(id, name) { }
protected override Enumeration<Colors> Create(int id, string name) => new Colors(id,name);
}