[英]Custom enum base class for flags
我正在按照Microsoft 的建議制作自定義枚舉 class,但努力制作支持標志樣式枚舉的版本。
當嘗試將兩個實例按位或一起創建一個不存在的新實例時,就會出現問題。
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 IEnumerable<TEnum> GetAll() =>
typeof(T).GetFields(BindingFlags.Public | BindingFlags.Static | BindingFlags.DeclaredOnly)
.Where(info => enumerationType.IsAssignableFrom(info.FieldType))
.Select(f => f.GetValue(null))
.Cast<T>();
public static Enumeration<TEnum> operator |(Enumeration<TEnum> left, Enumeration<TEnum> right)
{
// This is the problem method!
// I can obviously bitwise or together the two values, but how do I create an instance
// of TEnum from here so that is has a valid name?
// For instance, Colors.Red | Colors.Blue would need to be an instance where
// Id == (1 << 0 | 1 << 1) and Name == "Red, Blue".
}
// 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) { }
}
如果這是一個 xy 問題,我也很樂意聽取其他想法。
問題將始終是您無法從本地抽象基礎 class 內部構造Colors
的實例。 即,您可以將泛型約束為具有new()
但不具有特定的構造函數,例如new(int, string)
。
因此,一種選擇是在具體 class 本身內部定義(並為枚舉的每個實例重新定義)運算符
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}");
}
}
它工作的實時示例,但我懷疑這不是您想要做的: https://dotnetfiddle.net/KBQEt4
另一種選擇是為每個枚舉提供創建自身的智能(即,繞過缺乏特定的構造函數約束),然后您可以在基礎 class 上使用運算符:
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);
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.