Подтвердить что ты не робот

Любой трюк для определения перечисления как флагов/полномочий 2 без необходимости в калькуляторе?

Я знаю, что могу размножаться, но, будучи ленивым программированием, я не хочу.

Кто-нибудь придумал какое-то колдовство для автоматического номера перечислений как силы двух?

Вот пример, который я хотел бы сделать конкретным:

[Flags]
private enum Targets : uint
{
    None = 0,
    Campaigns = 1,
    CampaignGroups = 2,
    Advertisers = 4,
    AdvertiserGroups = 8,
    AffiliateGroups = 16,
    Affiliates = 32,
    Creatives = 64,
    DetailedLeads = 128,
    DetailedSales = 256,
    ProgramLeads = 512,
    CreativeDeployments = 1024,
    CampaignCategories = 2048,
    Payouts = 4096,
    All = uint.MaxValue
}
4b9b3361

Ответ 1

Запишите значения как сдвинутые биты и пусть компилятор выполнит математику:

[Flags]
private enum Targets : uint
{
    None                = 0,
    Campaigns           = 1,
    CampaignGroups      = 2 << 0,
    Advertisers         = 2 << 1,
    AdvertiserGroups    = 2 << 2,
    AffiliateGroups     = 2 << 3,
    Affiliates          = 2 << 4,
    Creatives           = 2 << 5,
    DetailedLeads       = 2 << 6,
    DetailedSales       = 2 << 7,
    ProgramLeads        = 2 << 8,
    CreativeDeployments = 2 << 9,
    CampaignCategories  = 2 << 10,
    Payouts             = 2 << 11,
    // etc.
}

Предложение Джеймса тоже хорошее. На самом деле мне нравится этот путь еще лучше. Вы также можете написать это следующим образом:

[Flags]
private enum Targets : uint
{
    None                = 0,
    Campaigns           = 1 << 0,
    CampaignGroups      = 1 << 1,
    Advertisers         = 1 << 2,
    AdvertiserGroups    = 1 << 3,
    AffiliateGroups     = 1 << 4,
    // etc.
}

Ответ 2

Использование шестнадцатеричной нотации немного проще, чем десятичная нотация (калькулятор не требуется):

[Flags]
private enum Targets : uint
{
    None                = 0,
    Campaigns           = 0x01,
    CampaignGroups      = 0x02,
    Advertisers         = 0x04,
    AdvertiserGroups    = 0x08,
    AffiliateGroups     = 0x10,
    Affiliates          = 0x20,
    Creatives           = 0x40,
    DetailedLeads       = 0x80,
    DetailedSales       = 0x100,
    ProgramLeads        = 0x200,
    CreativeDeployments = 0x400,
    CampaignCategories  = 0x800,
    Payouts             = 0x1000,
    // and the pattern of doubling continues
    // 0x2000
    // 0x4000
    // 0x8000
    // 0x10000
}

Не так элегантно, как решения Коди и Джеймса, но не требует калькулятора.

Ответ 3

Ускорьте вперед на пять лет вперед и, начиная с С# 7.0, вы можете использовать новый числовой двоичный литерал, чтобы упростить объявление флагов перечисления.

[Flags]
private enum Targets : uint
{
    None = 0,
    Campaigns =             0b0000_0000_0000_0001,
    CampaignGroups =        0b0000_0000_0000_0010,
    Advertisers =           0b0000_0000_0000_0100,
    AdvertiserGroups =      0b0000_0000_0000_1000,
    AffiliateGroups =       0b0000_0000_0001_0000,
    Affiliates =            0b0000_0000_0010_0000,
    Creatives =             0b0000_0000_0100_0000,
    DetailedLeads =         0b0000_0000_1000_0000,
    DetailedSales =         0b0000_0001_0000_0000,
    ProgramLeads =          0b0000_0010_0000_0000,
    CreativeDeployments =   0b0000_0100_0000_0000,
    CampaignCategories =    0b0000_1000_0000_0000,
    Payouts =               0b0001_0000_0000_0000,
    All = uint.MaxValue
}

https://docs.microsoft.com/en-us/dotnet/csharp/whats-new/csharp-7#numeric-literal-syntax-improvements

Ответ 4

Вот еще один альтернативный подход:

[Flags]
public enum COURSECOMPONENT_T : int
{
    Everything = -1,
    Nothing = 0,
    AttendanceRegisters = 1,
    Checklists = 2 * AttendanceRegisters,
    Competencies = 2 * Checklists,
    Content = 2 * Competencies,
    CourseFiles = 2 * Content,
    Discussions = 2 * CourseFiles,
    DisplaySettings = 2 * Discussions,
    Dropbox = 2 * DisplaySettings,
    Faq = 2 * Dropbox,
    Forms = 2 * Faq,
    Glossary = 2 * Forms,
    Grades = 2 * Glossary,
    GradesSettings = 2 * Grades,
    Groups = 2 * GradesSettings,
    Homepages = 2 * Groups,
    IntelligentAgents = 2 * Homepages,
    Links = 2 * IntelligentAgents,
    LtiLink = 2 * Links,
    LtiTP = 2 * LtiLink,
    Navbars = 2 * LtiTP,
    News = 2 * Navbars,
    QuestionLibrary = 2 * News,
    Quizzes = 2 * QuestionLibrary,
    ReleaseConditions = 2 * Quizzes,
    Rubrics = 2 * ReleaseConditions,
    Schedule = 2 * Rubrics,
    SelfAssessments = 2 * Schedule,
    Surveys = 2 * SelfAssessments,
    ToolNames = 2 * Surveys,
    Widgets = 2 * ToolNames,
}

Ответ 5

Я делаю следующее:

 using System;

 [Flags]
 public enum AnimalCharacteristics : long
 {
     Tail = 1 << AnimalCharacteristicsBitPositions.Tail,
     Eyes = 1 << AnimalCharacteristicsBitPositions.Eyes,
     Furry = 1 << AnimalCharacteristicsBitPositions.Furry,
     Bipedal = 1 << AnimalCharacteristicsBitPositions.Bipedal
 }

 internal enum AnimalCharacteristicsBitPositions : int
 {
     Tail = 0,
     Eyes,
     Furry,
     Bipedal
 }

 public class Program
 {
     public static void Main()
     {
         var human = AnimalCharacteristics.Eyes | AnimalCharacteristics.Bipedal;
         var dog = AnimalCharacteristics.Eyes | AnimalCharacteristics.Tail | AnimalCharacteristics.Furry;

         Console.WriteLine($"Human: {human} ({(long)human})");
         Console.WriteLine($"Dog: {dog} ({(long)dog})");
     }
 }

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

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

Ответ 6

#define BITS  \
    F(Campaigns) \
    F(Quizzes) \
    F(Groups) \
    F(Homepages)

#define F(x) x##_BIT,

enum bits {
    BITS
};

#undef F
#define F(x) x = (1 << x##_BIT),

enum flags {
    BITS
};