C# 检查枚举是否有任何公共标志
假设我有这个扩展方法:C# 检查枚举是否有任何公共标志,c#,enums,flags,enum-flags,C#,Enums,Flags,Enum Flags,假设我有这个扩展方法: public static bool HasAnyFlagInCommon(this System.Enum type, Enum value) { var flags = value.ToString().Split(new string[] { ", " }, StringSplitOptions.None); foreach (var flag in flags) {
public static bool HasAnyFlagInCommon(this System.Enum type, Enum value)
{
var flags = value.ToString().Split(new string[] { ", " },
StringSplitOptions.None);
foreach (var flag in flags)
{
if (type.ToString() == flag)
return true;
}
return false;
}
以及以下情况:
[Flags]
enum Bla
{
A = 0,
B = 1,
C = 2,
D = 4
}
Bla foo = Bla.A | Bla.B;
Bla bar = Bla.A;
bar.HasAnyFlagInCommon(foo); //returns true
我想检查foo是否有与bar相同的标志,但是在扩展方法中必须有更好的方法来实现这种行为
我也这样试过,但总是正确的:
public static bool HasAnyFlagInCommon(this System.Enum type, Enum value)
{
var flags = Enum.GetValues(value.GetType()).Cast<Enum>()
.Where(item => value.HasFlag(item));
foreach (var flag in flags)
{
if (type == flag)
return true;
}
return false;
}
public static bool HasAnyFlagInCommon(此系统.枚举类型,枚举值)
{
var flags=Enum.GetValues(value.GetType()).Cast()
.Where(item=>value.HasFlag(item));
foreach(标志中的var标志)
{
如果(类型==标志)
返回true;
}
返回false;
}
您可以简单地将枚举值强制转换为ulong(以考虑底层类型不是int的默认类型的可能性)。如果结果是这样的!=0,至少设置了一个标志
ulong theValue = (ulong)value;
return (theValue != 0);
记住,在一天结束时,枚举由byte、sbyte、short、ushort、int、uint、long或ulong中的一个来支持
设置的标志与在备份类型中打开的对应位相同。仅当所有位均关闭时,上面的ulong才会为0
更新
该问题是在发布此答案后编辑的,因此,以下是对该更新的修改:
然后,要查看枚举是否有与该枚举的另一个实例相同的标志,可以使用按位and。如果两者都设置了任何公共位位置,则结果将为非零:
var anyFlagsInCommon = ((ulong)value) & ((ulong)compareTo);
差不多
public static bool HasAnyFlagInCommon(this System.Enum type, Enum value)
{
return (((long)type) & ((long)value)) != 0;
}
&
为两个枚举中设置的任何位提供1
,因此如果存在任何此类位,则结果为非零
(我使用了
long
,希望它适用于枚举下的任何类型;int
在您的情况下应该可以。)我们有一个扩展方法,它基于本网站中描述的Has()扩展方法:。它应该比转换为字符串快,但我还没有检查性能。相关子集为:
/// <summary>
/// Checks if an enumerated type contains a value
/// </summary>
public static bool Has<T>(this Enum value, T check) {
Type type = value.GetType();
//determine the values
object result = value;
_Value parsed = new _Value(check, type);
if (parsed.Signed is long) {
return (Convert.ToInt64(value)& (long)parsed.Signed) == (long)parsed.Signed;
}
else if (parsed.Unsigned is ulong) {
return (Convert.ToUInt64(value) & (ulong)parsed.Unsigned) == (ulong)parsed.Unsigned;
}
else {
return false;
}
}
//class to simplfy narrowing values between
//a ulong and long since either value should
//cover any lesser value
private class _Value {
//cached comparisons for tye to use
private static Type _UInt64 = typeof(ulong);
private static Type _UInt32 = typeof(long);
public long? Signed;
public ulong? Unsigned;
public _Value(object value, Type type) {
//make sure it is even an enum to work with
if (!type.IsEnum) {
throw new ArgumentException("Value provided is not an enumerated type!");
}
//then check for the enumerated value
Type compare = Enum.GetUnderlyingType(type);
//if this is an unsigned long then the only
//value that can hold it would be a ulong
if (compare.Equals(_Value._UInt32) || compare.Equals(_Value._UInt64)) {
this.Unsigned = Convert.ToUInt64(value);
}
//otherwise, a long should cover anything else
else {
this.Signed = Convert.ToInt64(value);
}
}
}
//
///检查枚举类型是否包含值
///
公共静态bool具有(此枚举值,T检查){
Type Type=value.GetType();
//确定值
对象结果=值;
_解析值=新值(检查,键入);
if(parsed.Signed为长){
返回(Convert.ToInt64(value)和(long)parsed.Signed)=(long)parsed.Signed;
}
else if(parsed.Unsigned为ulong){
返回(Convert.ToUInt64(value)&(ulong)parsed.Unsigned)==(ulong)parsed.Unsigned;
}
否则{
返回false;
}
}
//类来简化在
//一个ulong和long-since值
//覆盖任何较小的价值
私有类_值{
//供tye使用的缓存比较
专用静态类型_UInt64=类型(ulong);
专用静态类型_UInt32=类型(长);
公众长期签名;
公共乌龙?未签名;
公共值(对象值,类型){
//确保它甚至是要使用的枚举
如果(!type.IsEnum){
抛出新ArgumentException(“提供的值不是枚举类型!”);
}
//然后检查枚举值
类型比较=Enum.getUnderlineType(类型);
//如果这是一个无符号长字符串,则
//可以容纳它的值将是一个ulong
如果(比较等于(_值._UInt32)|比较等于(_值._UInt64)){
this.Unsigned=Convert.ToUInt64(值);
}
//否则,long应该包括其他内容
否则{
this.Signed=Convert.ToInt64(值);
}
}
}
我想你想错了,我编辑了我的问题来澄清问题。仍然使用基础数字可能是一个解决方案。此外,即使这是“是否设置了任何已定义的标志”,如果以某种方式设置了一个不是已定义标志之一的位,它也不会返回正确的结果。这个答案不正确。它不可编译。@Kit:如果它是在静态类中声明的(因为所有扩展方法都必须是静态的),那么它应该可以编译。