2012-05-11 2 views
42

Ich weiß, ich kann multiplizieren, aber die faule Programmierung Ich bin ich will nicht.Irgendein Trick, um eine Enum als Flags/Potenzen von 2 zu definieren, ohne irgendwann einen Taschenrechner zu benötigen?

Hat jemand irgendeine Zauberei erfunden, um die Enums als Zweierpotenzen zu nummerieren?

Hier ist das Beispiel, das ich gerade haben es konkret zu machen:

[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 
} 
+3

Multiplizieren Sie den vorherigen Wert von 2? –

+5

einfachste Sache ist es, sie bis zu 2^64 zu speichern? – JeremyWeir

+4

Dafür sind Rechner da. Sie sollten Hex-Werte verwenden, nur um mit Multiplikation der Basis 16 geübt zu bleiben. :) – IAbstract

Antwort

90

die Werte Schreiben als Bits verschoben und lassen Sie den Compiler die Mathematik:

[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. 
} 

James Vorschlag ist gut, auch. Tatsächlich mag ich diesen Weg noch besser. Man könnte es auch so schreiben:

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

Ich mache etwas ähnliches, außer anstelle von 2, verwende ich 1 << 1, 1 << 2, 1 << 3, etc. –

+2

Da der zugrunde liegende Typ Ihres Enum ist "Uint", ist es wirklich '1u << 0 , '1u << 1' usw. Das könnte wichtig sein, wenn Sie zu' LastFlag = 1u << 31 'kommen. –

+0

'1 << n 'ist eine Abkürzung für ** bit n **. Wie in, wenn ich die Bits 2, 3 und 6 einer Zahl setzen wollte, würde ich die Zahl auf '(1 << 2) | setzen (1 << 3) | (1 << 6) Die Zahl, um die Sie verschieben, hat eine direkte Korrelation mit der Bitnummer, mit der Sie arbeiten. – indiv

36

Mit hexadezimaler Schreibweise ein wenig einfacher als Dezimalschreibweise ist auch (kein Rechner erforderlich):

[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 
} 

Nicht ganz so elegant wie Cody und James Lösungen , benötigt aber keinen Rechner.

+1

Ich habe dieses System häufig verwendet gesehen. Es ist also gut, es zu wissen, wenn Sie auf Code stoßen, der es verwendet. Ich benutze '1 <<' persönlich –

1

Schneller Vorlauf fünf Jahre in die Zukunft, und ab C# 7.0 können Sie das neue numerische Binärliteral verwenden, um die enum flags-Deklaration zu vereinfachen.

[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

+0

Natürlich kann das Ganze durch Einführung einer neuen Überladung für die Attributklasse Flags, die eine Bool "Auto" dauert, automatisiert werden. [Flags (true)] könnte dann dazu dienen, das Enum automatisch durch kontinuierliches linkes Bit zu füllen, das jedes Mitglied verschiebt. – Hugh

1

Hier ist noch eine weitere Alternative Ansatz:

[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, 
} 
Verwandte Themen