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);
    
}