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:如果它是在静态类中声明的(因为所有扩展方法都必须是静态的),那么它应该可以编译。