假设我有这个枚举:
[Flags]
enum Letters
{
A = 1,
B = 2,
C = 4,
AB = A | B,
All = A | B | C,
}
Run Code Online (Sandbox Code Playgroud)
要检查是否AB
已设置,我可以这样做:
if((letter & Letters.AB) == Letters.AB)
Run Code Online (Sandbox Code Playgroud)
有没有更简单的方法来检查组合标志常量的任何标志是否设置为以下?
if((letter & Letters.A) == Letters.A || (letter & Letters.B) == Letters.B)
Run Code Online (Sandbox Code Playgroud)
你可以换&
一些东西吗?
对于像这样的二进制文件来说不太稳定......
Chu*_*ula 159
在.NET 4中,您可以使用Enum.HasFlag方法:
using System;
[Flags] public enum Pet {
None = 0,
Dog = 1,
Cat = 2,
Bird = 4,
Rabbit = 8,
Other = 16
}
public class Example
{
public static void Main()
{
// Define three families: one without pets, one with dog + cat and one with a dog only
Pet[] petsInFamilies = { Pet.None, Pet.Dog | Pet.Cat, Pet.Dog };
int familiesWithoutPets = 0;
int familiesWithDog = 0;
foreach (Pet petsInFamily in petsInFamilies)
{
// Count families that have no pets.
if (petsInFamily.Equals(Pet.None))
familiesWithoutPets++;
// Of families with pets, count families that have a dog.
else if (petsInFamily.HasFlag(Pet.Dog))
familiesWithDog++;
}
Console.WriteLine("{0} of {1} families in the sample have no pets.",
familiesWithoutPets, petsInFamilies.Length);
Console.WriteLine("{0} of {1} families in the sample have a dog.",
familiesWithDog, petsInFamilies.Length);
}
}
Run Code Online (Sandbox Code Playgroud)
该示例显示以下输出:
// 1 of 3 families in the sample have no pets.
// 2 of 3 families in the sample have a dog.
Run Code Online (Sandbox Code Playgroud)
yey*_*man 121
如果您想知道字母是否包含AB中的任何字母,您必须使用AND&运算符.就像是:
if ((letter & Letters.AB) != 0)
{
// Some flag (A,B or both) is enabled
}
else
{
// None of them are enabled
}
Run Code Online (Sandbox Code Playgroud)
Tho*_*que 58
我使用扩展方法来编写这样的东西:
if (letter.IsFlagSet(Letter.AB))
...
Run Code Online (Sandbox Code Playgroud)
这是代码:
public static class EnumExtensions
{
private static void CheckIsEnum<T>(bool withFlags)
{
if (!typeof(T).IsEnum)
throw new ArgumentException(string.Format("Type '{0}' is not an enum", typeof(T).FullName));
if (withFlags && !Attribute.IsDefined(typeof(T), typeof(FlagsAttribute)))
throw new ArgumentException(string.Format("Type '{0}' doesn't have the 'Flags' attribute", typeof(T).FullName));
}
public static bool IsFlagSet<T>(this T value, T flag) where T : struct
{
CheckIsEnum<T>(true);
long lValue = Convert.ToInt64(value);
long lFlag = Convert.ToInt64(flag);
return (lValue & lFlag) != 0;
}
public static IEnumerable<T> GetFlags<T>(this T value) where T : struct
{
CheckIsEnum<T>(true);
foreach (T flag in Enum.GetValues(typeof(T)).Cast<T>())
{
if (value.IsFlagSet(flag))
yield return flag;
}
}
public static T SetFlags<T>(this T value, T flags, bool on) where T : struct
{
CheckIsEnum<T>(true);
long lValue = Convert.ToInt64(value);
long lFlag = Convert.ToInt64(flags);
if (on)
{
lValue |= lFlag;
}
else
{
lValue &= (~lFlag);
}
return (T)Enum.ToObject(typeof(T), lValue);
}
public static T SetFlags<T>(this T value, T flags) where T : struct
{
return value.SetFlags(flags, true);
}
public static T ClearFlags<T>(this T value, T flags) where T : struct
{
return value.SetFlags(flags, false);
}
public static T CombineFlags<T>(this IEnumerable<T> flags) where T : struct
{
CheckIsEnum<T>(true);
long lValue = 0;
foreach (T flag in flags)
{
long lFlag = Convert.ToInt64(flag);
lValue |= lFlag;
}
return (T)Enum.ToObject(typeof(T), lValue);
}
public static string GetDescription<T>(this T value) where T : struct
{
CheckIsEnum<T>(false);
string name = Enum.GetName(typeof(T), value);
if (name != null)
{
FieldInfo field = typeof(T).GetField(name);
if (field != null)
{
DescriptionAttribute attr = Attribute.GetCustomAttribute(field, typeof(DescriptionAttribute)) as DescriptionAttribute;
if (attr != null)
{
return attr.Description;
}
}
}
return null;
}
}
Run Code Online (Sandbox Code Playgroud)
Art*_*tru 30
.NET 4或更高版本中有HasFlag方法.
if(letter.HasFlag(Letters.AB))
{
}
Run Code Online (Sandbox Code Playgroud)
Luk*_*uka 20
如果可以使用.NET 4或更高版本,则使用HasFlag()方法
例子
letter.HasFlag(Letters.A | Letters.B) // both A and B must be set
Run Code Online (Sandbox Code Playgroud)
与...一样
letter.HasFlag(Letters.AB)
Run Code Online (Sandbox Code Playgroud)
Tam*_*ege 12
如果真的让你烦恼,你可以写一个这样的函数:
public bool IsSet(Letters value, Letters flag)
{
return (value & flag) == flag;
}
if (IsSet(letter, Letters.A))
{
// ...
}
// If you want to check if BOTH Letters.A and Letters.B are set:
if (IsSet(letter, Letters.A & Letters.B))
{
// ...
}
// If you want an OR, I'm afraid you will have to be more verbose:
if (IsSet(letter, Letters.A) || IsSet(letter, Letters.B))
{
// ...
}
Run Code Online (Sandbox Code Playgroud)
要检查是否设置了AB,我可以这样做:
if((letter&Letters.AB)== Letters.AB)
有没有更简单的方法来检查组合标志常量的任何标志是否设置为以下?
这就验证了两个 A和B被设置,并忽略任何其他标志是否被设置.
Run Code Online (Sandbox Code Playgroud)if((letter & Letters.A) == Letters.A || (letter & Letters.B) == Letters.B)
这就验证了无论 A或B被设置,并忽略任何其他标志是否被设定或没有.
这可以简化为:
if(letter & Letters.AB)
Run Code Online (Sandbox Code Playgroud)
这是二进制操作的C; 将它应用于C#应该很简单:
enum {
A = 1,
B = 2,
C = 4,
AB = A | B,
All = AB | C,
};
int flags = A|C;
bool anything_and_a = flags & A;
bool only_a = (flags == A);
bool a_and_or_c_and_anything_else = flags & (A|C);
bool both_ac_and_anything_else = (flags & (A|C)) == (A|C);
bool only_a_and_c = (flags == (A|C));
Run Code Online (Sandbox Code Playgroud)
顺便提一下,问题示例中变量的命名是单数"字母",这可能意味着它只代表一个字母; 示例代码清楚地表明它是一组可能的字母并且允许多个值,因此请考虑重命名变量'letters'.
怎么样
if ((letter & Letters.AB) > 0)
Run Code Online (Sandbox Code Playgroud)
?
小智 6
对于任何类型的枚举,您可以在枚举上使用此扩展方法:
public static bool IsSingle(this Enum value)
{
var items = Enum.GetValues(value.GetType());
var counter = 0;
foreach (var item in items)
{
if (value.HasFlag((Enum)item))
{
counter++;
}
if (counter > 1)
{
return false;
}
}
return true;
}
Run Code Online (Sandbox Code Playgroud)
我创建了一个不需要检查Enum
类型的简单扩展方法:
public static bool HasAnyFlag(this Enum value, Enum flags)
{
return
value != null && ((Convert.ToInt32(value) & Convert.ToInt32(flags)) != 0);
}
Run Code Online (Sandbox Code Playgroud)
它也适用于可为空的枚举。标准HasFlag
方法没有,所以我创建了一个扩展来覆盖它。
public static bool HasFlag(this Enum value, Enum flags)
{
int f = Convert.ToInt32(flags);
return
value != null && ((Convert.ToInt32(value) & f) == f);
}
Run Code Online (Sandbox Code Playgroud)
一个简单的测试:
[Flags]
enum Option
{
None = 0x00,
One = 0x01,
Two = 0x02,
Three = One | Two,
Four = 0x04
}
[TestMethod]
public void HasAnyFlag()
{
Option o1 = Option.One;
Assert.AreEqual(true, o1.HasAnyFlag(Option.Three));
Assert.AreEqual(false, o1.HasFlag(Option.Three));
o1 |= Option.Two;
Assert.AreEqual(true, o1.HasAnyFlag(Option.Three));
Assert.AreEqual(true, o1.HasFlag(Option.Three));
}
[TestMethod]
public void HasAnyFlag_NullableEnum()
{
Option? o1 = Option.One;
Assert.AreEqual(true, o1.HasAnyFlag(Option.Three));
Assert.AreEqual(false, o1.HasFlag(Option.Three));
o1 |= Option.Two;
Assert.AreEqual(true, o1.HasAnyFlag(Option.Three));
Assert.AreEqual(true, o1.HasFlag(Option.Three));
}
Run Code Online (Sandbox Code Playgroud)
享受!
这里有很多答案,但我认为使用 Flags 最惯用的方法是 Letters.AB.HasFlag(letter) 或 (Letters.A | Letters.B).HasFlag(letter) 如果你没有已经有 Letters.AB。letter.HasFlag(Letters.AB) 只有在两者都有时才有效。
归档时间: |
|
查看次数: |
142051 次 |
最近记录: |