Расширение enum с помощью Flags мешает текущему использованию - PullRequest
2 голосов
/ 02 ноября 2011

У системы есть простое перечисление, подобное этому,

public enum SomeEnum : short
{ 
    Ok = 0,
    Missing = 17,
};

Это перечисление теперь находится в ситуации, когда мне нужно замаскировать в него дополнительную информацию без изменения внешнего вида существующих значений перечисления.Перечисление получит несколько новых значений,

[Flags]
public enum SomeEnum : short
{ 
    Ok = 0,
    Missing = 17,
    Blocking = 18, // Values could be anything
    Low  = 19,     // Values could be anything
};

Я боялся, что могут быть проблемы с текущим использованием перечисления.Похоже, я прав, но Я надеюсь, что с вашей помощью я ошибся .Использование до сегодняшнего дня построено вокруг SomeEnum.Ok.Также завтра, но хорошо нужна дополнительная информация.Мне нужно замаскировать значения перечисления, не влияя на его текущее поведение, которое может исходить из любой общей ссылки;

someEnumVariable.ToString()
(int)someEnumVariable
someVar = SomeEnum.Ok
Enum.Parse(typeOf(SomeEnum), someString)

Если я отмечу перечисление с помощью

var test = (SomeEnum.Ok | SomeEnum.Blocking);
Оба флага могут быть установлены, т.е. test.HasFlags(SomeEnum.Ok) или test.HasFlags(SomeEnum.Blocking), но перечисление представляется как SomeEnum.Blocking, что невозможно.

Есть идеи?

Ответы [ 3 ]

2 голосов
/ 02 ноября 2011

http://msdn.microsoft.com/en-us/library/system.flagsattribute.aspx

Я думаю, что краткое введение в двоичное ИЛИ в порядке.

|не позволяет вам просто вставить два целых числа в одну переменную.Он выполняет математическую операцию.

Следовательно, любое значение , отличное от 0 ИЛИ с 0, само вернет это значение.

Возможно, вы столкнетесь с непредвиденным поведением, есливы предоставляете значения флагов, которые не являются единичными битами, например, 1, 2, 4, 8, 16.

РЕДАКТИРОВАТЬ

Если вы хотите создать перечисление Flagsвокруг существующих значений, вы можете сделать это.Не используйте текущие зарезервированные биты 10001 (17) для любых других значений и будьте осторожны при проверке на Ok.

2 голосов
/ 02 ноября 2011

Поскольку значение SomeEnum.OK равно 0, вызов HasFlag(SomeEnum.OK) будет всегда возвращать true.Когда вы маскируете перечисления вместе, процесс основывается на том факте, что сумма любой комбинации значений перечисления будет уникальной.Обычно вы устанавливаете их, начиная со значений 2^0, 2^1, 2^2 и т. Д. Например:

[Flags]
public enum SomeEnum : short
{ 
    Ok = 1,
    Missing = 2,
    Blocking = 4, // Values could be anything
    Low  = 8,     // Values could be anything
}

Если вы хотите замаскировать значения вместе, вам придетсяиспользуйте атрибут Flags.Если вы не можете выполнить рефакторинг и изменить значение SomeEnum.OK, то вам, возможно, придется полагаться на SomeEnum[], а не на единственное маскированное значение SomeEnum.

EDIT Просто быстрое замечание по маскированию значений вместе с помощью перечисления, определенного выше.Возьмите следующий код:

var t1 = (int)(SomeEnum.OK | SomeEnum.Missing);       //t1 = 1 + 2 = 3
var t2 = (int)(SomeEnum.Missing | SomeEnum.Blocking); //t2 = 2 + 4 = 6
var t3 = (int)(SomeEnum.OK | SomeEnum.Low);           //t3 = 1 + 8 = 9
var t4 = (int)SomeEnum.OK;                            //t4 = 1
var s1 = (SomeEnum.Ok).ToString();                    //s1 = "Ok"
var s2 = (SomeEnum.Ok | SomeEnum.Missing).ToString(); //s2 = "Ok, Missing"

Когда эти элементы объединены в OR, .NET просто складывает значения вместе, чтобы создать новое уникальное значение, представляющее комбинацию элементов OR.Использование значений перечисления степеней 2 гарантирует, что комбинации всегда будут уникальными.

0 голосов
/ 02 ноября 2011

Вот пример того, как сделать это с помощью битового флага.Однако это, вероятно, заставит вас изменить существующие сравнения флагов.

 [FlagsAttribute] 
enum tester
{
    alpha = 1,
    beta = 2,
    gamma = 4,
    reggy=3
}

class Program
{
    static void Main(string[] args)
    {
        tester t = tester.alpha | tester.beta;
        if (t == tester.alpha)
            Console.WriteLine("alpha only");
        if ((t & tester.alpha) != 0)
            Console.WriteLine("alpha");
        if ((t & tester.beta) != 0)
            Console.WriteLine("beta");
        if ((t & tester.gamma) != 0)
            Console.WriteLine("gamma");
        if (t == (tester.beta | tester.alpha))
            Console.WriteLine("alphabeta");

        //this will produce alpha, beta, alphabeta
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...