【问题标题】:check if an enum has any flags in common [duplicate]检查枚举是否有任何共同的标志[重复]
【发布时间】:2012-12-13 18:38:53
【问题描述】:

考虑一下我有这个扩展方法:

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

【问题讨论】:

    标签: c# enums flags enum-flags


    【解决方案1】:

    您可以简单地将 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);
    

    【讨论】:

    • 我认为您的想法有误,我编辑了我的问题以澄清问题。仍然使用底层数字可能是一个解决方案。
    • 此外,即使这是“是否设置了任何已定义的标志”,如果以某种方式设置了不是定义的标志。
    【解决方案2】:

    类似

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

    &amp; 为两个枚举中设置的任何位提供1,因此如果有 any 个这样的位,则结果非零。

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

    【讨论】:

    • 这个答案不正确。它无法编译。
    • @Kit:如果在静态类中声明它应该编译得很好(因为所有扩展方法都必须如此)。
    【解决方案3】:

    我们有一个基于本网站描述的 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);
                }
    
            }
        }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-09-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-07-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多