如果我有一个包含标志枚举的变量,我可以以某种方式迭代该特定变量中的位值吗?或者我是否必须使用Enum.GetValues迭代整个枚举并检查哪些枚举?
很多时候,我看到使用十六进制值的标志枚举声明.例如:
[Flags]
public enum MyEnum
{
None = 0x0,
Flag1 = 0x1,
Flag2 = 0x2,
Flag3 = 0x4,
Flag4 = 0x8,
Flag5 = 0x10
}
Run Code Online (Sandbox Code Playgroud)
当我声明一个枚举时,我通常会这样声明:
[Flags]
public enum MyEnum
{
None = 0,
Flag1 = 1,
Flag2 = 2,
Flag3 = 4,
Flag4 = 8,
Flag5 = 16
}
Run Code Online (Sandbox Code Playgroud)
是否有理由或理由为什么有些人选择用十六进制而不是十进制来写值?我看到它的方式,使用十六进制值并意外写Flag5 = 0x16而不是更容易混淆Flag5 = 0x10.
我想知道将enum标志的所有位设置为1 的通用方法.我只想enum为所有比较返回一个,而不管其他枚举.
这段代码有效;
[Flags]
public enum SomeRightEnum : uint
{
CanDoNothing = 0,
CanDoSomething = 1 << 0,
CanDoSomethingElse = 1 << 1,
CanDoYetAnotherThing = 1 << 2,
...
DoEverything = 0xFFFFFFFF
}
Run Code Online (Sandbox Code Playgroud)
但是在上面的代码中,因为它是uint我们设置"F"的数量,如果是的话它将不起作用int.
所以,我会感激的所有位设置的一个通用的方法enum标志为1,而不管数据类型(iNT, int64,uint等)
一位开发人员建议我们将一周中的选择日期存储为7个字符的1和0字符串,即周一和周五的"1000100".我更喜欢(强烈建议)一个带有Flags枚举和按位操作的解决方案,我认为这是一种更简洁的方法,对其他开发人员应该更容易理解.
[Flags()]
public enum Weekdays : int
{
Monday = 1,
Tuesday = 2,
Wednesday = 4,
Thursday = 8,
Friday = 16,
Saturday = 32,
Sunday = 64
}
Run Code Online (Sandbox Code Playgroud)
然而,当我开始实现一个示例解决方案时,我意识到简单的字符串方法可能更容易:当然,如果您只是查看数据,则位串比"17"更明显.我发现C#按位运算反直觉且非常冗长:
Weekdays workDays = Weekdays.Monday | Weekdays.Tuesday;
if ((workDays & Weekdays.Monday) == Weekdays.Monday)
{...}
Run Code Online (Sandbox Code Playgroud)
当然,这可以很好地包含在扩展方法中,但是我们突然最终得到的代码行数与字符串解决方案的数量相同,我几乎不能认为按位代码更容易阅读.
话虽这么说,我仍然会使用标志枚举和按位操作.我能想到的主要好处是
那么我如何向同事出售逐位解决方案呢?我是不是该?使用此方法比字符串有什么其他好处?完成示例项目后,我发现团队仍然选择了基于字符串的解决方案.我需要一些更好/更强的论点.为什么要使用Flags枚举而不是简单的位串?
我有一个Enum Flags网格,其中每个记录都是一行复选框,用于确定记录的标志值.这是系统提供的通知列表,用户可以选择(每个)他们希望如何传递的通知:
[Flag]
public enum NotificationDeliveryType
{
InSystem = 1,
Email = 2,
Text = 4
}
Run Code Online (Sandbox Code Playgroud)
我找到了这篇文章,但他正在取回一个标志值,并且他将它绑定在控制器中,就像这样(一周中的几天概念):
[HttpPost]
public ActionResult MyPostedPage(MyModel model)
{
//I moved the logic for setting this into a helper
//because this could be re-used elsewhere.
model.WeekDays = Enum<DayOfWeek>.ParseToEnumFlag(Request.Form, "WeekDays[]");
...
}
Run Code Online (Sandbox Code Playgroud)
我无法找到MVC 3模型绑定器可以处理标志的任何地方.谢谢!
所以我正在构建一个MSNP(windows live messenger)客户端.我有这个功能列表
public enum UserCapabilities : long
{
None = 0,
MobileOnline = 1 << 0,
MSN8User = 1 << 1,
RendersGif = 1 << 2,
....
MsgrVersion7 = 1 << 30,
MsgrVersion8 = 1 << 31,
MsgrVersion9 = 1 << 32,
}
Run Code Online (Sandbox Code Playgroud)
完整列表http://paste.pocoo.org/show/383240/
服务器将每个用户的功能作为一个长整数发送给客户端,我将其转换为UserCapabilities
capabilities = Int64.Parse(e.Command.Args[3]);
user._capabilities = (UserCapabilities)capabilities;
Run Code Online (Sandbox Code Playgroud)
这很好,至少有一个用户(能力值为1879474220),我能做到
Debug.WriteLine(_msgr.GetUser(usr).Capabilities);
Run Code Online (Sandbox Code Playgroud)
这将输出
RendersGif, RendersIsf, SupportsChunking, IsBot, SupportsSChannel, SupportsSipInvite, MsgrVersion5, MsgrVersion6, MsgrVersion7
Run Code Online (Sandbox Code Playgroud)
但是对于具有(3055849760)能力值的另一个用户,当我这样做时,我只输出相同的数字
3055849760
Run Code Online (Sandbox Code Playgroud)
我希望看到的是功能列表,与其他用户一样.
我确信这种情况有一个非常合理的原因,但无论我多么努力地向谷歌提问,我都找不到答案.
请帮我 :)
有没有办法在XAML中设置多个枚举标志(传统上由|代码隐藏中的|分隔)?我尝试过类似的东西:
<ns:SomeControl Flags="FlagA|FlagB" />
Run Code Online (Sandbox Code Playgroud)
但那没用.
这是枚举定义:
[Flags]
enum Animals
{
None = 0,
Dog = 1,
Cat = 2,
Horse = 4,
Zebra = 8,
}
Run Code Online (Sandbox Code Playgroud)
现在,给定以下代码,为什么HasFlag方法对值Animals.None返回true?
Animals myAnimals = Animals.Dog | Animals.Horse;
var hasNone = myAnimals.HasFlag(Animals.None); //true! Why?
var hasCat = myAnimals.HasFlag(Animals.Cat); //false
var hasDog = myAnimals.HasFlag(Animals.Dog); //true
var hasHorse = myAnimals.HasFlag(Animals.Horse); //true
var hasZebra = myAnimals.HasFlag(Animals.Zebra); //false
Run Code Online (Sandbox Code Playgroud) 好的,所以我们在C++ 17,对C++中一个非常好的bitflags接口仍然没有一个令人满意的答案.
我们enum将其成员值放入封闭范围,但是隐式转换为它们的基础类型,因此可以用作 - 如果它们是位标志但拒绝重新分配回枚举而不进行转换.
我们已经enum class解决了名称范围问题,因此它们的值必须显式命名MyEnum::MyFlag或者甚至MyClass::MyEnum::MyFlag,但是它们不会隐式转换为它们的基础类型,因此不能在没有无休止地来回转换的情况下用作位标志.
最后,我们有以下的旧位域C:
struct FileFlags {
unsigned ReadOnly : 1;
unsigned Hidden : 1;
...
};
Run Code Online (Sandbox Code Playgroud)
这样做的缺点是没有好的方法可以将自身整体化 - 人们不得不求助于使用memset或者转换地址或类似的方法来覆盖整个值或者一次初始化它或者一次操作多个位.它也无法命名给定标志的值,而不是它的地址 - 因此没有名称代表0x02,而使用枚举时有这样的名称,因此枚举命名组合时很容易标志,例如FileFlags::ReadOnly | FileFlags::Hidden- 对于比特字段来说,根本不是一个很好的方式.
此外,我们仍然有简单constexpr或#define命名位值,然后根本不使用枚举.这有效,但完全将位值与基础位标志类型分离.也许这最终不是最糟糕的方法,特别是如果位标志值constexpr在一个结构中,为它们提供自己的名称范围?
struct FileFlags {
constexpr static uint16_t ReadOnly = 0x01u;
constexpr static uint16_t Hidden = 0x02u;
...
}
Run Code Online (Sandbox Code Playgroud)
因此,就目前而言,我们有很多技术,但没有一种技术可以说是非常可靠
这是一个具有以下有效位标志的类型,它有自己的名称范围,这些位和类型应该可以与标准的按位运算符一起使用,例如| &^〜,它们应该与0之类的整数值相当,并且任何按位运算符的结果应该保持为命名类型,而不是转换为积分
所有这些都说,有很多尝试在C++中试图产生上述实体 -
DEFINE_ENUM_FLAG_OPERATORS(EnumType),然后定义运算符.&^〜以及相关的赋值操作,如| =等.enable_if元编程允许给定的枚举转换为支持缺失运算符的位标志类型,然后再静默返回.我想要一个可以与任何Flags样式枚举一起使用的通用函数来查看是否存在标志.
这不会编译,但如果有人有建议,我会很感激.
public static Boolean IsEnumFlagPresent<T>(T value,T lookingForFlag)
where T:enum
{
Boolean result = ((value & lookingForFlag) == lookingForFlag);
return result ;
}
Run Code Online (Sandbox Code Playgroud)