8

考虑我有这个扩展方法:

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 相同的标志,但必须有更好的方法在扩展方法中实现这种行为。

我也试过这样,但总是返回 true:

    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;
    }
4

3 回答 3

7

您可以简单地将 Enum 值转换为ulong(以考虑基础类型不是int的默认值的可能性)。如果结果 != 0,则至少设置了一个标志。

ulong theValue = (ulong)value;
return (theValue != 0);

请记住,在一天结束时,枚举由 byte、sbyte、short、ushort、int、uint、long 或 ulong 之一支持。

http://msdn.microsoft.com/en-us/library/sbbt4032.aspx

设置的标志与在支持类型中打开的相应位相同。如果所有位都关闭,则上面的ulong只会为 0。

更新

在发布此答案后对该问题进行了编辑,因此这里进行了修改以说明该更新:

然后查看枚举是否与该枚举的另一个实例有任何共同的标志,您可以使用按位与。如果两者都设置了任何公共位位置,则结果将非零:

var anyFlagsInCommon = ((ulong)value) & ((ulong)compareTo);
于 2012-12-13T18:41:12.923 回答
4

就像是

public static bool HasAnyFlagInCommon(this System.Enum type, Enum value)
{
    return (((long)type) & ((long)value)) != 0;
}

&给出了在两个枚举中设置的1任何位,所以如果有任何这样的位,结果是非零的。

(我已经使用long过,希望它适用于枚举基础的任何类型;int在你的情况下应该没问题。)

于 2012-12-13T19:55:30.143 回答
1

我们有一个基于本网站描述的Has()扩展方法的扩展方法:http: //somewebguy.wordpress.com/2010/02/23/enumeration-extensions-2。它应该比转换为字符串更快,但我还没有检查过性能。相关子集是:

    /// <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);
            }

        }
    }
于 2020-09-07T15:41:38.907 回答