用于检测(通过反射)Enum是否为“0”类型的策略;标志“;在C#中

本文关键字:策略 类型 检测 标志 反射 Enum 用于 是否 | 更新日期: 2023-09-27 18:25:56

我使用反射读取程序集中的类型(生成代码)。我可以看到,一些枚举本应标记有[Flags]属性,但编写这些枚举的人忘记添加此属性。

有没有可靠的方法来检测枚举何时可以被视为"标志"枚举?

我目前的策略是按降序读取枚举,并检查元素(last-1)*2==元素(last)的值。

这在大多数情况下都很有效,除非我有0、1和2值的枚举(可以是标志也可以不是标志)。


编辑:

我想检测为标志的枚举示例:

public enum EnumIsFlag1
{
    ItemA = 2,
    ItemB = 4,
    ItemC = ItemA + ItemB,
    ItemD = 32,
    ItemE = 64,
}

edit:我的问题没有重复。。。主持人显然没有阅读我的问题

用于检测(通过反射)Enum是否为“0”类型的策略;标志“;在C#中

很明显,这个问题只能用启发式方法解决,但我知道这就是你想要的。

通常,标志枚举的大多数成员都有一个位集。所以我会计算只有一个比特集的成员的数量(例如,是二的幂)。

然后,您可以设计一种启发式方法,例如:

//Is this a flags enum?
var totalCount = ...;
var powerOfTwoCount = ...;
if (totalCount < 3) return false; //Can't decide.
if (powerOfTwoCount >= totalCount * 0.95) return true; //Looks like flags
//Probably need some cases for small values of totalCount.

在合法标志枚举中可以设置多个位的唯一原因是标志的组合。但此类枚举项的数量通常很少。

这个答案详细介绍了两者之间的差异,它们非常小:只是一些字符串格式化行为。

对于您的问题,严格的答案是可以使用反射检查任何类型的标志枚举。其他任何东西都只需要由一个人来检查。您可以像这样直接检查Flags属性;

[Flags]
enum Foo
{
    A = 0,
    B = 1,
    C = 4
}
enum Bar
{
    A = 0,
    B = 1,
    C = 4
}

bool IsFlagsEnum(Type t) 
{
    var attr = t.GetCustomAttributes(typeof(FlagsAttribute), true).FirstOrDefault();
    var result = attr != null;
    return result;
}
Console.WriteLine(IsFlagsEnum(typeof(Foo))); // True
Console.WriteLine(IsFlagsEnum(typeof(Bar))); // False