Enum.HasFlag, why no Enum.SetFlag?

前端 未结 8 2037
别跟我提以往
别跟我提以往 2020-12-24 05:38

I have to build an extension method for each flag type I declare, like so:

public static EventMessageScope SetFlag(this EventMessageScope flags, 
    EventMe         


        
8条回答
  •  一生所求
    2020-12-24 06:20

    public static class SomeEnumHelperMethodsThatMakeDoingWhatYouWantEasier
    {
        public static T IncludeAll(this Enum value)
        {
            Type type = value.GetType();
            object result = value;
            string[] names = Enum.GetNames(type);
            foreach (var name in names)
            {
                ((Enum) result).Include(Enum.Parse(type, name));
            }
    
            return (T) result;
            //Enum.Parse(type, result.ToString());
        }
    
        /// 
        /// Includes an enumerated type and returns the new value
        /// 
        public static T Include(this Enum value, T append)
        {
            Type type = value.GetType();
    
            //determine the values
            object result = value;
            var parsed = new _Value(append, type);
            if (parsed.Signed is long)
            {
                result = Convert.ToInt64(value) | (long) parsed.Signed;
            }
            else if (parsed.Unsigned is ulong)
            {
                result = Convert.ToUInt64(value) | (ulong) parsed.Unsigned;
            }
    
            //return the final value
            return (T) Enum.Parse(type, result.ToString());
        }
    
        /// 
        /// Check to see if a flags enumeration has a specific flag set.
        /// 
        /// Flags enumeration to check
        /// Flag to check for
        /// 
        public static bool HasFlag(this Enum variable, Enum value)
        {
            if (variable == null)
                return false;
    
            if (value == null)
                throw new ArgumentNullException("value");
    
            // Not as good as the .NET 4 version of this function, 
            // but should be good enough
            if (!Enum.IsDefined(variable.GetType(), value))
            {
                throw new ArgumentException(string.Format(
                    "Enumeration type mismatch.  The flag is of type '{0}', " +
                    "was expecting '{1}'.", value.GetType(), 
                    variable.GetType()));
            }
    
            ulong num = Convert.ToUInt64(value);
            return ((Convert.ToUInt64(variable) & num) == num);
        }
    
    
        /// 
        /// Removes an enumerated type and returns the new value
        /// 
        public static T Remove(this Enum value, T remove)
        {
            Type type = value.GetType();
    
            //determine the values
            object result = value;
            var parsed = new _Value(remove, type);
            if (parsed.Signed is long)
            {
                result = Convert.ToInt64(value) & ~(long) parsed.Signed;
            }
            else if (parsed.Unsigned is ulong)
            {
                result = Convert.ToUInt64(value) & ~(ulong) parsed.Unsigned;
            }
    
            //return the final value
            return (T) Enum.Parse(type, result.ToString());
        }
    
        //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 readonly Type _UInt32 = typeof (long);
            private static readonly Type _UInt64 = typeof (ulong);
    
            public readonly long? Signed;
            public readonly 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(_UInt32) || compare.Equals(_UInt64))
                {
                    Unsigned = Convert.ToUInt64(value);
                }
                    //otherwise, a long should cover anything else
                else
                {
                    Signed = Convert.ToInt64(value);
                }
            }
        }
    }
    

提交回复
热议问题