Сравнение перечисления отмечает в C#

Android SDK может сказать вам это прекрасно:

getResources().getConfiguration().orientation
13
задан Razzie 6 July 2009 в 12:05
поделиться

7 ответов

Лично я думаю, что это нормально, потому что вы его обернули в единую функцию. Если бы у вас был этот код, разбросанный по всей программе, я думаю, у вас возникли бы некоторые проблемы, но то, что вы создали, улучшает ясность везде, где он используется, а сама функция достаточно ясно показывает, что она делает.

Это, конечно, моё мнение.

Вы могли бы использовать ключевое слово is, которое может немного помочь

public static bool IsSet<T>(this T value, T flags) where T : Enum
{ 
    if (value is int)
    {
        return ((int)(object)a & (int)(object)b) == (int)(object)b);
    }
    //etc...
6
ответ дан 1 December 2019 в 18:55
поделиться

Я написал набор методов расширения для перечислений на случай, если он вам понадобится:

public static class EnumExtensions
{
    private static void CheckEnumWithFlags<T>()
    {
        if (!typeof(T).IsEnum)
            throw new ArgumentException(string.Format("Type '{0}' is not an enum", typeof(T).FullName));
        if (!Attribute.IsDefined(typeof(T), typeof(FlagsAttribute)))
            throw new ArgumentException(string.Format("Type '{0}' doesn't have the 'Flags' attribute", typeof(T).FullName));
    }

    public static bool IsFlagSet<T>(this T value, T flag) where T : struct
    {
        CheckEnumWithFlags<T>();
        long lValue = Convert.ToInt64(value);
        long lFlag = Convert.ToInt64(flag);
        return (lValue & lFlag) != 0;
    }

    public static IEnumerable<T> GetFlags<T>(this T value) where T : struct
    {
        CheckEnumWithFlags<T>();
        foreach (T flag in Enum.GetValues(typeof(T)).Cast<T>())
        {
            if (value.IsFlagSet(flag))
                yield return flag;
        }
    }

    public static T SetFlags<T>(this T value, T flags, bool on) where T : struct
    {
        CheckEnumWithFlags<T>();
        long lValue = Convert.ToInt64(value);
        long lFlag = Convert.ToInt64(flags);
        if (on)
        {
            lValue |= lFlag;
        }
        else
        {
            lValue &= (~lFlag);
        }
        return (T)Enum.ToObject(typeof(T), lValue);
    }

    public static T SetFlags<T>(this T value, T flags) where T : struct
    {
        return value.SetFlags(flags, true);
    }

    public static T ClearFlags<T>(this T value, T flags) where T : struct
    {
        return value.SetFlags(flags, false);
    }

    public static T CombineFlags<T>(this IEnumerable<T> flags) where T : struct
    {
        CheckEnumWithFlags<T>();
        long lValue = 0;
        foreach (T flag in flags)
        {
            long lFlag = Convert.ToInt64(flag);
            lValue |= lFlag;
        }
        return (T)Enum.ToObject(typeof(T), lValue);
    }
}

Главный недостаток в том, что вы не можете указать , где T: Enum : это явно запрещено («Ограничение не может быть специальным классом 'System.Enum'»), поэтому методы расширения будут отображаться в intellisense для всех структур ... Я добавил метод CheckEnumWithFlags , чтобы проверить, является ли тип на самом деле это перечисление и имеет атрибут Flags .


ОБНОВЛЕНИЕ: Джон Скит недавно создал интересную библиотеку под названием UnconstrainedMelody , которая делает точно такие же вещи и работает с общим ограничение типа, упомянутое выше

10
ответ дан 1 December 2019 в 18:55
поделиться

На мой взгляд, это слишком сложно. Как насчет этого (имея в виду, что enum всегда сопоставляется с типом целочисленного значения):

public static bool IsSet<T>(T value, T flags) where T : struct
{
    // You can add enum type checking to be perfectly sure that T is enum, this have some cost however
    // if (!typeof(T).IsEnum)
    //     throw new ArgumentException();
    long longFlags = Convert.ToInt64(flags);
    return (Convert.ToInt64(value) & longFlags) == longFlags;
}
15
ответ дан 1 December 2019 в 18:55
поделиться

Это должно выполнить работу для типов enum с любыми базовыми типами:

public static bool IsSet<T>(this T value, T flags) where T : struct
{
    return (Convert.ToInt64(value) & Convert.ToInt64(flags)) ==
        Convert.ToInt64(flags);
}

Convert.ToInt64 используется, потому что 64-битное целое число является «самым широким "Возможен интегральный тип, к которому могут быть приведены все значения перечисления (даже ulong ). Обратите внимание, что char не является допустимым базовым типом. Кажется, что он не действителен в C #, но в целом действителен в CIL / для CLR.

Кроме того, вы не можете принудительно применить ограничение общего типа для перечисления (т.е. , где T: struct ); Лучшее, что вы можете сделать, - это использовать , где T: struct , чтобы заставить T быть типом значения, а затем, при необходимости, выполнить динамическую проверку, чтобы убедиться, что T является тип перечисления.

Для полноты, вот мой очень краткий тестовый набор:

static class Program
{
    static void Main(string[] args)
    {
        Debug.Assert(Foo.abc.IsSet(Foo.abc));
        Debug.Assert(Bar.def.IsSet(Bar.def));
        Debug.Assert(Baz.ghi.IsSet(Baz.ghi));
    }

    enum Foo : int
    {
        abc = 1,
        def = 10,
        ghi = 100
    }

    enum Bar : sbyte
    {
        abc = 1,
        def = 10,
        ghi = 100
    }

    enum Baz : ulong
    {
        abc = 1,
        def = 10,
        ghi = 100
    }
}
7
ответ дан 1 December 2019 в 18:55
поделиться

Я использовал это для сравнения флагов

public static bool IsSet<T>(this T input, T match)
{
    return (Convert.ToUInt32(input) & Convert.ToUInt32(match)) != 0;
}

Здесь вы можете выполнять различные преобразования. От int к короткому к длинному.

0
ответ дан 1 December 2019 в 18:55
поделиться

или ... public static bool IsSet (это значение Enum, сравнение Enum) { int baseValue = значение.ToInt32 (); int compareValue = compare.ToInt32 (); если (baseValue == 0) вернуть ложь; return ((baseValue & compareValue) == compareValue); }

0
ответ дан 1 December 2019 в 18:55
поделиться

Просто используйте метод Enum.HasFlag () !

2
ответ дан 1 December 2019 в 18:55
поделиться
Другие вопросы по тегам:

Похожие вопросы: