RSS

Tag Archives: Enum

Constant Enum: Circular definition

If you have declared an enum field as constant you may get following exception:

The evaluation of the constant value for … involves a circular Definition.

The code where this exception appears looks like:

private const Parity Parity = Parity.None;

Well, thats strange. There is no error. I declare a constant field with the same name as the name of the type. This is allowed, because I can also write following line of code, and this would compile:

private const String String = "HELLO";

The problem with enums is that the compiler interprets the Parity from Parity.None not as the name of the enum-type but as the name of the field. Hence, we have a circular reference because the constant is defined by the constant itself. To solve the compile error you have two options: either you add the fully qualified name to the third Parity value or you change the name of the field.

private const Parity Parity = System.IO.Ports.Parity.None;
//or
private const Parity ParityValue = Parity.None;

Note: If you use tools like ReSharper then after a code clean up the qualifier might be removed. If that is the case I would suggest you to use the second Option, to rename the the name of the field.

 
Leave a comment

Posted by on April 29, 2013 in C-Sharp

 

Tags: ,

Get desired Attribute of any Enum

A very interesting feature that I was missing is to get a specific attribute that is set on an enum.

public static T GetAttribute<T>(this Enum enumObj) where T : Attribute
{
    FieldInfo fieldInfo = enumObj.GetType().GetField(enumObj.ToString());

    if (fieldInfo == null)
        throw new InvalidOperationException("The value "  + enumObj +
                        " ist not defined as a member of the enum" + enumObj.GetType() + ".");

    object[] attribArray = fieldInfo.GetCustomAttributes(typeof(T), false);

    if (attribArray.Length == 0)
        throw new InvalidOperationException(typeof(T) + " ist not an attribute of " +
                        enumObj.GetType());

    try
    {
        return (T)Convert.ChangeType(attribArray[0], typeof(T));
    }
    catch (System.Exception)
    {
        throw new InvalidOperationException("Cannot cast " + attribArray[0].GetType() + " to " +
                        typeof(T) + ". Please specify the generic parameter to its correct type.");
    }
}

This piece can be used as en extension method on every enum. As generic parameter T you should use the type of the attribute you want to get from the enum.

Note
* The attribute you want to get has to be set on the enum.
* You should always be precise with the type of generic parameter T, to get exactly the Attribute you desire.
* On enums with the Flag attribute set, this method will not work everytime.

Example: By passing “Attribute” as parameter T you will get a InvalidCastException if the DescriptionAttribute is set. It has also no sense to pass “Attribute” because then, in the best case, you will get the first attribute that is set on the enum.

Example:

public enum Month
{
    [Description("1st month of the year")]
    January,
    [Description("2dn month of the year")]
    February,
    [Description("3rd month of the year")]
    March,
    [...]
}

Reading the description from the value is done following:

Month m = Month.January;
string s = m.GetAttribute<DescriptionAttribute>().Description;

The value of variable s is then “1st month of the year”.

Flag enum

Example of an enum with flag attribute set:

[Flags]
public enum Month
{
    [Description("1st month of the year")]
    January= 0x1,
    [Description("2dn month of the year")]
    February= 0x2,
    [Description("3rd month of the year")]
    March= 0x4,
    [Description("4th month of the year")]
    April= 0x8,
    [Description("5th month of the year")]
    May= 0x10,
    [Description("6th month of the year")]
    June= 0x20,
    [...]
    [Description("12th month of the year")]
    December= 0x1000,
    [Description("All months in spring")]
    Spring = March | April | May | June,
    [Description("All months in winter")]
    Spring = December | January | February | March,
}

Please be avare of using flags on enums when you call GetArrtibute().
The problem is of its internal nature. The values the fields in the flag enum has to be of power of 2.
Therefore considering the example above, if you set flag Jannuary | February the resulting value is 3, but 3 is not defined as a value in the bitfield.
Therefore it doesn’t exist a description for value 3.

An example that works:

Month m= Month.Spring;
string s = m.GetAttribute<DescriptionAttribute>().Description;

The value of string s is:
All months in spring

Another example that won’t work

Months m = Month.Spring | Month.Winter;
string s= m.GetAttribute<DescriptionAttribute>().Description;

Here we will get an InvalidOperationException saying.
The value “Spring, Winter” ist not defined as a member of the enum Month.

 
2 Comments

Posted by on September 24, 2010 in C-Sharp

 

Tags: ,