Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Общие вопросы по .NET и C# > проверка флага в enum


Автор: nmn 26.1.2009, 22:28
проблема с проверкой флагов в перечислениях, вернее в удобстве такой проверки
поэтому хочется сделать что то вроде
Код

static class FlagEnumHelper
{
 public static bool isSet(... src, ... flag)
}

собственно проблема, что нужно вместо троеточия, чтобы работало со всеми перечислениями?

Автор: Anyone 26.1.2009, 22:45
Возможно, object

Автор: nmn 26.1.2009, 22:52
не дописал, должно быть так
Код

static class FlagEnumHelper
{
 public static bool isSet(... src, ... flag)
{
return (src&flag)==flag;
}
}

Автор: mihryak 26.1.2009, 23:01
а интами разве не катит?
Код

        [Flags]
        enum Test
        {
            A = 1,
            B = 2,
            C = 4
        }

        private static bool TestEnum(int value, int flag)
        {
            return (value & flag) == flag;
        }

        static void Main(string[] args)
        {
            Test test = Test.A | Test.B;
            Console.WriteLine(TestEnum((int) test, (int) Test.B));
            Console.WriteLine(TestEnum((int)test, (int)Test.C));
            Console.WriteLine(TestEnum((int)test, (int) (Test.A | Test.B)));
            Console.WriteLine(TestEnum((int)test, (int)(Test.A | Test.C)));

            Console.ReadKey();
        }

Автор: Anyone 26.1.2009, 23:04
Я так понял, flag - это маска, то есть переменная целого типа и функция возвратит true тогда и только тогда, когда все биты с значением 1 источника и маски совпадут, при этом где у маски ноль - у источника может быть что годно. В таком случае src должен иметь такой же тип. Или я что-то не так понял?

Автор: nmn 26.1.2009, 23:10
Цитата(mihryak @ 26.1.2009,  23:01)
а интами разве не катит?
Код

        [Flags]
        enum Test
        {
            A = 1,
            B = 2,
            C = 4
        }

        private static bool TestEnum(int value, int flag)
        {
            return (value & flag) == flag;
        }

        static void Main(string[] args)
        {
            Test test = Test.A | Test.B;
            Console.WriteLine(TestEnum((int) test, (int) Test.B));
            Console.WriteLine(TestEnum((int)test, (int)Test.C));
            Console.WriteLine(TestEnum((int)test, (int) (Test.A | Test.B)));
            Console.WriteLine(TestEnum((int)test, (int)(Test.A | Test.C)));

            Console.ReadKey();
        }

приводить типы, оно то конечно можно и наверное так и буду делать если не найдется обходной вариант
идеально было бы через обобщения, но компилятору не нравится битовая операция :(

Автор: mihryak 26.1.2009, 23:19
можно и с обобщениями, через небольшой хак в обмен на строгую типизацию

Код

        private static bool TestEnum<T>(T value, T flag) where T : struct
        {
            if (!value.GetType().IsEnum || !flag.GetType().IsEnum)
            {
                throw new ArgumentException("Invalid enum type");
            }

            return (Convert.ToInt32(value) & Convert.ToInt32(flag)) == Convert.ToInt32(flag);
        }

Код

Console.WriteLine(TestEnum<Test>(test, Test.B));

Автор: diadiavova 26.1.2009, 23:21
Цитата(nmn @  26.1.2009,  22:52 Найти цитируемый пост)
return (src&flag)==flag;

Я что-то вообще не пойму, почему это вдруг должно заработать. 
Я бы вместо этого попробовал сделать так
Код

return (src|flag)^src==0;

Автор: mihryak 26.1.2009, 23:27
Цитата(diadiavova @  27.1.2009,  00:21 Найти цитируемый пост)
Цитата(nmn @  26.1.2009,  22:52 Найти цитируемый пост)
return (src&flag)==flag;
Я что-то вообще не пойму, почему это вдруг должно заработать. 


10010111 - src
AND
00010010 - flag
==
00010010 - == flag

10010111 - src
AND
00011010 - flag
==
00010010 - != flag

Автор: diadiavova 26.1.2009, 23:38
mihryak, Надо же, и правда работает  smile 

Автор: nmn 27.1.2009, 02:45
Цитата(mihryak @ 26.1.2009,  23:19)
можно и с обобщениями, через небольшой хак в обмен на строгую типизацию

Код

        private static bool TestEnum<T>(T value, T flag) where T : struct
        {
            if (!value.GetType().IsEnum || !flag.GetType().IsEnum)
            {
                throw new ArgumentException("Invalid enum type");
            }

            return (Convert.ToInt32(value) & Convert.ToInt32(flag)) == Convert.ToInt32(flag);
        }

Код

Console.WriteLine(TestEnum<Test>(test, Test.B));

мда, уж лучше приводить к int сразу, чем пройти через проверки типов и все равно приводить smile

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)