Determine if Enum value is NOT compound in C #

EDIT:

Most people believe that flag enumerations should always have the powers of two. This may be best practice, but I do not define the listings here, rather check them out and want to cover all possible scenarios within reasonable limits. The question really is the correct way to implement a function with a name EnumUtilities.IsValueDefinedAndComposite<T>.

ORIGINAL MAIL:

Consider the following Enum:

[Flags]
public enum TestWithFlags { One = 1, Two = 2, }

Below is the result Enum.IsDefinedwith various values ​​cast as TestWithFlags.

Conclusion:

(1). Defined: True:  One.
(2). Defined: True:  Two.
(3). Defined: False: 100.
(4). Defined: False: One, Two.
(5). Defined: ?????: One, Two.

I cannot figure out how to determine if an enumeration value is composite. See Function EnumUtilities.IsValueDefinedAndComposite<T>in the code below.

Here is the complete code for convenience.

using System;
using System.Collections.Generic;
using System.Linq;

namespace MyNamespace
{
    [Flags]
    public enum TestWithFlags { One = 1, Two = 2, }

    public static class Program
    {
        private static void Main (string [] args)
        {
            TestWithFlags value;

            value = TestWithFlags.One; // True.
            Console.WriteLine("(1). Defined: {0}:  {1}.", Enum.IsDefined(typeof(TestWithFlags), value), value.ToString());

            value = TestWithFlags.Two; // True.
            Console.WriteLine("(2). Defined: {0}:  {1}.", Enum.IsDefined(typeof(TestWithFlags), value), value.ToString());

            value = (TestWithFlags) 100; // False.
            Console.WriteLine("(3). Defined: {0}: {1}.", Enum.IsDefined(typeof(TestWithFlags), value), value.ToString());

            value = TestWithFlags.One | TestWithFlags.Two; // False.
            Console.WriteLine("(4). Defined: {0}: {1}.", Enum.IsDefined(typeof(TestWithFlags), value), value.ToString());

            value = TestWithFlags.One | TestWithFlags.Two; // Not implemented.
            Console.WriteLine("(5). Defined: N/A:   {1}.", EnumUtilities.IsValueDefinedAndComposite(value), value.ToString());

            Console.WriteLine();
            Console.Write("Press any key to continue...");
            Console.ReadKey(true);
        }
    }

    public static class EnumUtilities
    {
        public static List<T> GetValues<T> ()
            where T: struct, IComparable, IFormattable, IConvertible
        {
            EnumUtilities.ThrowOnNonEnum<T>();

            var list = Enum.GetValues(typeof(T)).OfType<T>().ToList().ConvertAll<T>(v => ((T) v));

            return (list);
        }

        public static bool IsValueDefinedAndComposite<T> (T value)
            where T: struct, IComparable, IFormattable, IConvertible
        {
            EnumUtilities.ThrowOnEnumWithoutFlags<T>();

            var values = EnumUtilities.GetValues<T>();

            var result = false;
            //var result = values.Count(v => (value | v) == value) > 1;
            // How to determine whether the argument [value] is composite.

            return (result);
        }

        public static bool IsValueDefinedAndNonComposite<T> (T value)
            where T: struct, IComparable, IFormattable, IConvertible
        {
            EnumUtilities.ThrowOnNonEnum<T>();

            return (Enum.IsDefined(typeof(T), value));
        }

        public static bool IsValueDefined<T> (T value)
            where T: struct, IComparable, IFormattable, IConvertible
        {
            EnumUtilities.ThrowOnNonEnum<T>();

            return (EnumUtilities.IsValueDefinedAndNonComposite(value) || EnumUtilities.IsValueDefinedAndComposite(value));
        }

        private static void ThrowOnNonEnum<T> ()
        {
            if (!typeof(T).IsEnum)
            {
                throw (new ArgumentException("The generic argument [<T>] must be an enumeration.", "T: " + typeof(T).FullName));
            }
        }

        private static void ThrowOnEnumWithFlags<T> ()
        {
            EnumUtilities.ThrowOnNonEnum<T>();

            var attributes = typeof(T).GetCustomAttributes(typeof(FlagsAttribute), false);

            if (attributes.Length > 0)
            {
                throw (new ArgumentException("The generic argument [<T>] must be an enumeration without the [FlagsAttribute] applied.", "T: " + typeof(T).FullName));
            }
        }

        private static void ThrowOnEnumWithoutFlags<T> ()
        {
            EnumUtilities.ThrowOnNonEnum<T>();

            var attributes = typeof(T).GetCustomAttributes(typeof(FlagsAttribute), false);

            if (attributes.Length == 0)
            {
                throw (new ArgumentException("The generic argument [<T>] must be an enumeration with the [FlagsAttribute] applied.", "T: " + typeof(T).FullName));
            }
        }
    }
}
+4
7

, {One = 1<<0, Two = 1<< 1, ALot=1<<20}, . , . "" enum { Sign = 0x80, Mantissa=0x78, Power = 0x7}.


, :

: , 0 . ( & ~enumValue - )

var remainingBits = value; 
foreach (var enumValue in GetAllValuesOfEnum(....))
{
  if (value == enumValue) return "ExisitngNonComposite";
  var remainingBits = current & ~enumValue;
  if (remainingBits == 0) return "Composite";
}
return "CanNotBeRepresented";    

, :

  • enum
  • ( Flags 32/64 int/long ) , )
  • (0xFFFFFFFF) - , (value & ~ allFilgesOrTogether) == 0 .
+1

- ( !):

   public static bool IsValueDefinedAndComposite<T>(T value)
        where T : struct, IComparable, IFormattable, IConvertible
    {
        EnumUtilities.ThrowOnEnumWithoutFlags<T>();

        var values = EnumUtilities.GetValues<T>();


        var result = values.OfType<T>().Contains(value);
        //var result = values.Count(v => (value | v) == value) > 1;
        // How to determine whether the argument [value] is composite.

        return (result);
    }

, , , , .

+4

; , , , .

. , 2

bool IsPowerOfTwo(ulong x)
{
     return (x != 0) && ((x & (x - 1)) == 0);
}

, ( ).

+2

, , , : , F string string format, , .

Microsoft:

, . ( Flags ), , . , . F.

, , , ThrowOnNonEnum.

:

    public static bool IsValueDefinedAndComposite<T>(T value)
        where T : struct, IComparable, IFormattable, IConvertible
    {
        EnumUtilities.ThrowOnNonEnum<T>();

        var valueAsString = Enum.Format(typeof (T), value, "F");

        // If the value contains a comma, then it is defined and composite
        if (valueAsString.Contains(","))
        {
            return true;
        }
        else
        {
            // If the value cannot be completely determined by the enumeration entries, it will be numeric. 
            // This is one possible method for testing this.
            double valueAsDouble = 0;
            return !(Double.TryParse(valueAsString, out valueAsDouble));
        }
    }

5 6, :

 value = TestWithFlags.One | TestWithFlags.Two; // True
 Console.WriteLine("(5). Defined: {0}: {1}.", EnumUtilities.IsValueDefinedAndComposite(value), value.ToString());

 value = (TestWithFlags)6; // False
 Console.WriteLine("(6). Defined: {0}: {1}.", EnumUtilities.IsValueDefinedAndComposite(value), value.ToString());

:

(1). Defined: True:  One.
(2). Defined: True:  Two.
(3). Defined: False: 100.
(4). Defined: False: One, Two.
(5). Defined: True: One, Two.
(6). Defined: False: 6.
+1

.

, (TestWithFlags) 2^NUMBER, , .

0

, , () ? ?

if( 0 != (myCompositeEnum & TestWithFlags.One) )
{
    // then TestWithFalgs.One is in the composite.
}

BTW, Enum .
fooobar.com/questions/49243/....

0

, , , enum , :

[Flags]
public enum TestWithFlags
{
    One = 1,
    Two = 2,
    Four = 4,
    Seven = Four | Two | One,
    Eight = 8,
    Nine = Eight | One,
}

, "" ? " " " enum, - "?

, " enum, - ", :

public static class EnumUtilities
{
    public static List<T> GetValues<T> ()
        where T: struct, IComparable, IFormattable, IConvertible
    {
        EnumUtilities.ThrowOnNonEnum<T>();

        var list = Enum.GetValues(typeof(T)).OfType<T>().ToList().ConvertAll<T>(v => ((T) v));

        return (list);
    }

    private static ulong[] GetValuesAsUint64<T>()
        where T : struct, IComparable, IFormattable, IConvertible
    {
        EnumUtilities.ThrowOnNonEnum<T>();
        IList eList = Enum.GetValues(typeof(T));
        ulong[] list = new ulong[eList.Count];
        for (int i = 0; i < eList.Count; i++)
        {
            list[i] = Convert.ToUInt64(eList[i]);
        }
        return list;
    }

    public static bool IsValueDefinedOrComposite<T>(T value)
        where T : struct, IComparable, IFormattable, IConvertible
    {
        EnumUtilities.ThrowOnEnumWithoutFlags<T>();

        var intValue = Convert.ToUInt64(value);
        var intValues = GetValuesAsUint64<T>();

        if (intValue == 0)
        {
            return intValues.Contains(intValue);
        }
        else
        {
            int matches = 0;

            foreach (var test in intValues)
            {
                if ((test & intValue) == test)
                {
                    matches++;
                    intValue &= ~(test);
                }
            }

            return matches > 0 && intValue == 0;
        }
    }

    public static bool IsValueDefinedAndNonComposite<T> (T value)
        where T: struct, IComparable, IFormattable, IConvertible
    {
        EnumUtilities.ThrowOnNonEnum<T>();

        return (Enum.IsDefined(typeof(T), value));
    }

    public static bool IsValueDefinedAndComposite<T>(T value)
        where T : struct, IComparable, IFormattable, IConvertible
    {
        return IsValueDefinedOrComposite(value) && !IsValueDefinedAndNonComposite(value);
    }

    private static void ThrowOnNonEnum<T> ()
    {
        if (!typeof(T).IsEnum)
        {
            throw (new ArgumentException("The generic argument [<T>] must be an enumeration.", "T: " + typeof(T).FullName));
        }
    }

    private static void ThrowOnEnumWithFlags<T> ()
    {
        EnumUtilities.ThrowOnNonEnum<T>();

        var attributes = typeof(T).GetCustomAttributes(typeof(FlagsAttribute), false);

        if (attributes.Length > 0)
        {
            throw (new ArgumentException("The generic argument [<T>] must be an enumeration without the [FlagsAttribute] applied.", "T: " + typeof(T).FullName));
        }
    }

    private static void ThrowOnEnumWithoutFlags<T> ()
    {
        EnumUtilities.ThrowOnNonEnum<T>();

        var attributes = typeof(T).GetCustomAttributes(typeof(FlagsAttribute), false);

        if (attributes.Length == 0)
        {
            throw (new ArgumentException("The generic argument [<T>] must be an enumeration with the [FlagsAttribute] applied.", "T: " + typeof(T).FullName));
        }
    }
}  

, (u) ; ( - ). , , # 1.0 . .

, , bitmasking; .

0

Source: https://habr.com/ru/post/1546431/


All Articles