У меня есть коллекция Enum, состоящая из |, могу ли я проверить, находится ли в ней определенное значение? [Дубликат]

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

Итак, если вы используете Angular, React или любые другие фреймворки, которые делают два способа связывания данных, эта проблема просто исправлена ​​для вас, поэтому простым языком ваш результат undefined на первом этапе, поэтому вы получили result = undefined до получения данных, а затем, как только вы получите результат , он будет обновляться и привязываться к новому значению, которое отвечает на ваш вызов Ajax ...

Но как вы можете сделать это в чистом javascript или jQuery, например, как вы задали этот вопрос?

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

Например, в вашем случае, в котором вы используете jQuery, вы можете сделать что-то вроде этого:

$(document).ready(function(){
    function foo() {
        $.ajax({url: "api/data", success: function(data){
            fooDone(data); //after we have data, we pass it to fooDone
        }});
    };

    function fooDone(data) {
        console.log(data); //fooDone has the data and console.log it
    };

    foo(); //call happens here
});

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

1133
задан Vogel612 11 October 2014 в 11:48
поделиться

9 ответов

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

myProperties.AllowedColors = MyColor.Red | MyColor.Green | MyColor.Blue;

Обратите внимание, что [Flags] сам по себе не изменяет это вообще - все, что он делает, - это хорошее представление с помощью .ToString() Метод:

enum Suits { Spades = 1, Clubs = 2, Diamonds = 4, Hearts = 8 }
[Flags] enum SuitsFlags { Spades = 1, Clubs = 2, Diamonds = 4, Hearts = 8 }

...

var str1 = (Suits.Spades | Suits.Diamonds).ToString();
           // "5"
var str2 = (SuitsFlags.Spades | SuitsFlags.Diamonds).ToString();
           // "Spades, Diamonds"

Также важно отметить, что [Flags] автоматически не делает значения перечисления равными двум. Если вы опустите числовые значения, перечисление не будет работать так, как можно было бы ожидать в побитовых операциях, потому что по умолчанию значения начинаются с 0 и приращения.

Неправильное объявление:

[Flags]
public enum MyColors
{
    Yellow,
    Green,
    Red,
    Blue
}

Значения, объявленные таким образом, будут желтыми = 0, зеленым = 1, красным = 2, синим = 3. Это сделает его бесполезно для использования в качестве флагов.

Вот пример правильного объявления:

[Flags]
public enum MyColors
{
    Yellow = 1,
    Green = 2,
    Red = 4,
    Blue = 8
}

Чтобы получить отдельные значения в вашем свойстве, вы можете сделать это:

if((myProperties.AllowedColors & MyColor.Yellow) == MyColor.Yellow)
{
    // Yellow has been set...
}

if((myProperties.AllowedColors & MyColor.Green) == MyColor.Green)
{
    // Green has been set...
}    

или в .NET 4 и более поздних версиях:

if (myProperties.AllowedColors.HasFlag(MyColor.Yellow))
{
    // Yellow has been set...
}

Под обложками

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

 Yellow: 00000001
 Green:  00000010
 Red:    00000100
 Blue:   00001000

Аналогично, после того, как вы установили свое свойство AllowedColors к красному, зеленому и синему (какие значения, где OR'ed трубой |), AllowedColors выглядит так

myProperties.AllowedColors: 00001110

Поэтому, когда вы извлекаете значение, которое вы на самом деле побитовое значение AND_ing значений

myProperties.AllowedColors: 00001110
             MyColor.Green: 00000010
             -----------------------
                            00000010 // Hey, this is the same as MyColor.Green!

Значение None = 0

И относительно использования 0 в вашем перечислении, цитируя из msdn:

[Flags]
public enum MyColors
{
    None = 0,
    ....
}
< blockquote>

Использовать None как имя перечислимой константы флага, значение которой равно нулю. Вы не можете использовать переменную None, указанную в побитовой операции И, чтобы проверить флаг, потому что результат всегда равен нулю. Однако вы можете выполнить логическое, а не поразрядное сравнение между числовым значением и перечислимой константой None, чтобы определить, установлены ли какие-либо биты в числовом значении.

Дополнительную информацию об атрибуте flags и его использовании можно найти в msdn и флажках проектирования в msdn

1766
ответ дан PersyJack 23 August 2018 в 17:27
поделиться

I недавно спросил о чем-то подобном.

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

Это позволяет:

[Flags]
public enum PossibleOptions : byte
{
    None = 0,
    OptionOne = 1,
    OptionTwo = 2,
    OptionThree = 4,
    OptionFour = 8,

    //combinations can be in the enum too
    OptionOneAndTwo = OptionOne | OptionTwo,
    OptionOneTwoAndThree = OptionOne | OptionTwo | OptionThree,
    ...
}

Тогда вы можете сделать:

PossibleOptions opt = PossibleOptions.OptionOneTwoAndThree 

if( opt.IsSet( PossibleOptions.OptionOne ) ) {
    //optionOne is one of those set
}

Мне это легче читать, чем большинство способов проверки включены флаги.

87
ответ дан Community 23 August 2018 в 17:27
поделиться

Для примера, который показывает декларацию и потенциальное использование, см. следующее:

namespace Flags
{
    class Program
    {
        [Flags]
        public enum MyFlags : short
        {
            Foo = 0x1,
            Bar = 0x2,
            Baz = 0x4
        }

        static void Main(string[] args)
        {
            MyFlags fooBar = MyFlags.Foo | MyFlags.Bar;

            if ((fooBar & MyFlags.Foo) == MyFlags.Foo)
            {
                Console.WriteLine("Item has Foo flag set");
            }
        }
    }
}
44
ответ дан Jaider 23 August 2018 в 17:27
поделиться

Флаги позволяют использовать битмаскирование внутри вашего перечисления. Это позволяет комбинировать значения перечисления, сохраняя, какие из них указаны.

[Flags]
public enum DashboardItemPresentationProperties : long
{
    None = 0,
    HideCollapse = 1,
    HideDelete = 2,
    HideEdit = 4,
    HideOpenInNewWindow = 8,
    HideResetSource = 16,
    HideMenu = 32
}
10
ответ дан Markus Safar 23 August 2018 в 17:27
поделиться

Вы также можете это сделать

[Flags]
public enum MyEnum
{
    None   = 0,
    First  = 1 << 0,
    Second = 1 << 1,
    Third  = 1 << 2,
    Fourth = 1 << 3
}

Я считаю, что бит-сдвиг проще, чем ввод 4,8,16,32 и так далее. Это не влияет на ваш код, потому что это все сделано во время компиляции

673
ответ дан Orion Edwards 23 August 2018 в 17:27
поделиться

В конструкторе if ((x & y) == y)... есть что-то слишком многословное, особенно если x AND y являются составными наборами флагов, и вы только хотите знать, есть ли какое-либо перекрытие.

In этот случай, все, что вам действительно нужно знать, - если после битмаскирования есть ненулевое значение [1].

[1] См. комментарий Хайме. Если бы мы были достоверно bitmasking , нам нужно было бы только проверить, что результат положительный. Но поскольку enum s может быть отрицательным, даже, как ни странно, в сочетании с атрибутом [Flags] , он защищен кодом для != 0, а не > 0.

Создание настроек @ andnil ...

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

namespace BitFlagPlay
{
    class Program
    {
        [Flags]
        public enum MyColor
        {
            Yellow = 0x01,
            Green = 0x02,
            Red = 0x04,
            Blue = 0x08
        }

        static void Main(string[] args)
        {
            var myColor = MyColor.Yellow | MyColor.Blue;
            var acceptableColors = MyColor.Yellow | MyColor.Red;

            Console.WriteLine((myColor & MyColor.Blue) != 0);     // True
            Console.WriteLine((myColor & MyColor.Red) != 0);      // False                
            Console.WriteLine((myColor & acceptableColors) != 0); // True
            // ... though only Yellow is shared.

            Console.WriteLine((myColor & MyColor.Green) != 0);    // Wait a minute... ;^D

            Console.Read();
        }
    }
}
13
ответ дан ruffin 23 August 2018 в 17:27
поделиться

Чтобы добавить Mode.Write:

Mode = Mode | Mode.Write;
15
ответ дан shA.t 23 August 2018 в 17:27
поделиться

@Nidonocu

Чтобы добавить другой флаг к существующему набору значений, используйте оператор присваивания OR.

Mode = Mode.Read;
//Add Mode.Write
Mode |= Mode.Write;
Assert.True(((Mode & Mode.Write) == Mode.Write)
  && ((Mode & Mode.Read) == Mode.Read)));
19
ответ дан steve_c 23 August 2018 в 17:27
поделиться

В расширении до принятого ответа в C # 7 флаги перечисления могут быть записаны с использованием двоичных литералов:

[Flags]
public enum MyColors
{
    None   = 0b0000,
    Yellow = 0b0001,
    Green  = 0b0010,
    Red    = 0b0100,
    Blue   = 0b1000
}

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

16
ответ дан Thorkil Holm-Jacobsen 23 August 2018 в 17:27
поделиться
Другие вопросы по тегам:

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