Ask a questionAsk a question
 

AnswerDetecting Explicitly Declared Enum Values

  • Wednesday, October 21, 2009 12:50 PMgmancoll Users MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     
    Hi,

    I'm looking for a way to determine whether the values of an enumeration have been defined explicitly in code or assigned automatically by the compiler, for a rule that I'm writing to prevent explicit definitions of values unless they are powers of 2.  Is there a way of detecting this case?  I can't seem to find any property on the Field object that will help to determine this.

    Thanks in advance,

    Graham

Answers

  • Wednesday, October 21, 2009 1:37 PMNicole Calinoiu Users MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     Answer
    If there are gaps, the values were explicitly assigned.  If there are no gaps, you can't tell.  StyleCop would probably be a better choice for implementing this rule.

    BTW, what you are describing actually runs counter to recommended design guidelines for .NET for at least public enums.
    • Marked As Answer bygmancoll Tuesday, October 27, 2009 2:46 PM
    •  

All Replies

  • Wednesday, October 21, 2009 1:37 PMNicole Calinoiu Users MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     Answer
    If there are gaps, the values were explicitly assigned.  If there are no gaps, you can't tell.  StyleCop would probably be a better choice for implementing this rule.

    BTW, what you are describing actually runs counter to recommended design guidelines for .NET for at least public enums.
    • Marked As Answer bygmancoll Tuesday, October 27, 2009 2:46 PM
    •  
  • Wednesday, October 21, 2009 3:16 PMgmancoll Users MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     
    Really?  I think you must be misunderstanding my rule as I maybe didn't explain it well enough.  I was looking to implement a rule which enforces the "avoid defining explicit values for enums unless they are powers of 2" guideline which is present in several published coding guidelines documents.

    From what you are saying, however, I don't think it will be possible.

    Thanks,

    Graham
  • Friday, October 23, 2009 10:32 AMRoahn LuoMSFT, ModeratorUsers MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     
    Hello Graham,

    Based on my understanding, we want to develop a custom rule for detecting the enum types: if it contains just two elements/items, we omit it; if it contains more that two elements/items and their value does not started with 0 (the default start value), there will be a violation to note user "avoid defining explicit values for enum". If I misunderstand you, please let me know.

    Drag and drop the assembly of the enum type to the IL DASM tool, we could see the elements/items of the enum type looks like:
    ======================================================
    .field public static literal valuetype ClassLibrary.MyColor Black = int32(0x0000000C)
    ======================================================

    Since we need to analyze the enum type, hence, we need to override the Check (TypeNode type) method, the code snippet looks like:
    ======================================================
    public override ProblemCollection  Check(TypeNode type)
    {
        if (!(type is EnumNode))
        {
            return null;
        }
        if (type.Members.Count > 2)
        {
            for (int i = 0; i < type.Members.Count; i++)
            {
                Field field = type.Members[i] as Field;
                // analyze the field here
            }
         }
         return this.Problems
    }
    ======================================================

    Best regards,
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.
    If you have any feedback, please tell us.
    Welcome to the All-In-One Code Framework!
  • Monday, October 26, 2009 11:58 AMNicole Calinoiu Users MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     
    I'm not sure which guidelines you're using, but this particular rule is actually a very bad idea.  The reason is a bit complicated, but here it goes...

    The values of an enum are exposed as constants on the type defined by the enum.  When a constant is referenced in code, it is its actual value, not the reference, that end up being included in the IL of the compiled assembly.  This causes no problems when a constant is used only within its own assembly.  However, a constant value can be changed in a referenced assembly without requiring the recompilation of a referencing assembly.  This means that the referencing assembly will be using an incorrect value of the changed constant unless it has been recompiled against the constant-defining assembly.

    Because of this, the .NET design guidelines recommend only using constants for values that will never change (http://msdn.microsoft.com/en-us/library/ms229057.aspx).  Since most enum values are arbitrary, they don't really meet this benchmark.  However, since they are usually arbitrary, they have no reason to change either.  Unfortunately, if we allow their values to be auto-generated, they can be changed merely by adding a new value anywhere other than at the end of the enum.  The best way to avoid this is to explicitly define enum values for at least public enums, then follow a coding guideline that prohibits changing existing enum values.  (Adding checks like code reviews and unit tests that verify that enum values are unchanges can also be of obvious benefit if you're willing to invest in them.)
  • Tuesday, October 27, 2009 2:46 PMgmancoll Users MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     
    Hi,

    right, I see your point.  The basis for the rule actually comes from the iDesign coding guidelines document (http://www.idesign.net/idesign/download/IDesign%20CSharp%20Coding%20Standard.zip) which states that recommendation.  I'm fairly sure I've seen it in other guidelines documents but can't locate them at the moment.

    Thanks for your explanation,

    Graham