我有一个枚举
:
public enum Flags {
COMMAND_MSG = 1,
COMMAND_FILE = 2,
COMMAND_ACTION = 4,
}
现在,假设我设置了多个值,例如:
Flags g = Flags.COMMAND_ACTION |Flags.COMMAND_MSG;
所以我有一个值为 5
的 int。
现在,从 5
我想看到它是以下内容的组合:Flags.COMMAND_ACTION |Flags.COMMAND_MSG;
(注意,我没有[Flags]
属性,因为我使用的是 protobuff 库,并且枚举是自动生成的。
我尝试了什么:
public string Show (Flags item)
{
var s="";
string.Join(",", Enum.GetValues(typeof(Flags))
.Cast<Flags>()
.Select(f=>(f & item) >0 ?f.ToString() :"") //check if bit is set
.Where(f=>!string.IsNullOrWhiteSpace(f))); //remove empty
return s;
}
所以 Show(5);
确实显示:COMMAND_MSG,COMMAND_ACTION
那么问题出在哪里?
我想将其转换为通用扩展方法:
public static string ToFlags<T>(this int val, T FlagType) where T : ??
{
return string.Join(",", Enum.GetValues(typeof(T))
.Cast<T>()
.Select(enumEntry => (enumEntry & val) > 0 ? enumEntry.ToString() : "")
.Where(f => !string.IsNullOrWhiteSpace(f)));
}
但是有一个错误,因为:
问题:
我应该应用哪个通用约束才能使其正常工作?
最佳答案
对于这种情况没有合适的通用类型约束。您可以将位运算应用于 int
,因此将枚举值转换为 int。 T
不能直接转换为int
;但是,您可以绕过 object
。
public static string ToFlags<T>(this T val)
where T : struct
{
return string.Join(",", Enum.GetValues(typeof(T))
.Cast<T>()
.Select(enumEntry => ((int)(object)enumEntry & (int)(object)val) > 0
? enumEntry.ToString() : "")
.Where(f => !string.IsNullOrWhiteSpace(f)));
}
注意:数字也有类似的情况。您不能说 where T : number
并对类型 T 的值应用数字运算符。
您还可以将 val
设为 T
并且您不必将 T
的类型作为方法参数传递。您已经将其作为通用类型参数传递。这已经足够了。编译器也很聪明,可以推断出 T
,因此您不必在调用方法时指定它。
// Test
Flags item = Flags.COMMAND_ACTION | Flags.COMMAND_MSG;
Console.WriteLine(item.ToFlags());
您可以将struct
指定为泛型类型约束,因为struct
代表值类型。它并不完美,但总比没有约束要好。
关于c# - 允许按位运算的通用约束?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27657323/