2012-05-11 9 views
42

Sé que puedo multiplicar pero siendo la programación perezosa que soy no quiero.¿Algún truco para definir una enumeración como flags/powers of 2 sin necesitar eventualmente una calculadora?

¿Alguien ha ideado alguna hechicería para numerar automáticamente las enumeraciones como potencias de dos?

Aquí está el ejemplo que acabo de hacer que el hormigón:

[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

Multiplicar el valor previo de 2? –

+5

lo más fácil es memorizarlos hasta 2^64? – JeremyWeir

+4

Para eso están las calculadoras. Debería usar valores hexadecimales solo para seguir practicando con la base multiplicadora 16. :) – IAbstract

Respuesta

90

Escribir los valores como desplazado trozos y dejar que el compilador de hacer los cálculos: sugerencia

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

de James es una buena, también. De hecho, me gusta de esta manera aún mejor. También podría escribir así:

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

Hago algo similar, excepto que en lugar de 2, uso 1 << 1, 1 << 2, 1 << 3, etc. –

+2

Dado que el tipo subyacente de tu enumeración es 'uint', es realmente' 1u << 0' , '1u << 1' etc. Eso podría ser importante cuando veas' LastFlag = 1u << 31'. –

+0

'1 << n' es la abreviatura de ** bit n **. Como en, si quisiera establecer los bits 2, 3 y 6 de un número, establecería el número en '(1 << 2) | (1 << 3) | (1 << 6) '. El número que cambias tiene una correlación directa con el número de bit en el que estás operando. – indiv

36

Utilizando la notación hexadecimal es un poco más simple que la notación decimal, así (sin necesidad de calculadora):

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

No es tan elegante como soluciones Cody y James , pero no requiere calculadora

+1

He visto este sistema ampliamente utilizado muchas veces. así que es bueno saberlo cuando te encuentres con el código que lo usa. Yo uso '1 <<' personalmente –

1

Avance rápido a cinco años en el futuro, y comenzando con C# 7.0 puede utilizar el nuevo literal numérico binario para simplificar la declaración de indicadores enum.

[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

Por supuesto, todo se puede automatizar mediante la introducción de una nueva sobrecarga para la clase de atributo Flags que toma un bool "Auto". Entonces, [Flags (true)] podría servir para que la enumeración se complete automáticamente con el bit izquierdo continuo cambiando cada miembro. – Hugh

1

Aquí hay otro enfoque alternativo:

[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, 
} 
Cuestiones relacionadas