DarkUrse
DarkUrse

Reputation: 2280

GetCustomAttributes getting me wrong attribute

I have a curious situation that I would like to understand better so that I can fix elegantly.

I have an enum with description attributes on each of the values as follow :

public enum LambdaPackageError : int
{
   __packageOffset = 100,

   // base errors
   __base_offset = __packageOffset,
   [Description("Base error 0")]
   BaseError0 = __base_offset,
   [Description("Base error 1")]
   BaseError1 = __base_offset + 1,
   [Description("Base error 2")]
   BaseError2 = __base_offset + 2,


   // extended errors
   __extended_offset = __packageOffset + 10,
   [Description("Extended error 0")]
   ExtendedError0 = __extended_offset,
   [Description("Extended error 1")]
   ExtendedError1 = __extended_offset+ 1
}

And now this is the snippet that would get the description attached to the enum entry :

public string GetDescriptionAttribute<T>(T value)
{
    var attr = typeof(T)
               .GetField(value.ToString())
               .GetCustomAttributes(typeof(DescriptionAttribute), false)
               .Cast<DescriptionAttribute>()
               .FirstOrDefault();

    return attr?.Description;
}

Nothing crazy here

GetDescriptionAttribute<LambdaPackageError>(LambdaPackageError.BaseError2);      // ==> Returns attribute, OK
GetDescriptionAttribute<LambdaPackageError>(LambdaPackageError.ExtendedError1);  // ==> Returns attribute, OK
GetDescriptionAttribute<LambdaPackageError>(LambdaPackageError.__packageOffset); // ==> Returns nothing, OK

However, this is the curiousity :

GetDescriptionAttribute<LambdaPackageError>(LambdaPackageError.BaseError0);      // ==> Returns nothing. Wait .. what ?

When I check what the above state does, it actually resolves it to LambdaPackageError.__base_offset rather than LambdaPackageError.BaseError0.

The obvious is that they have the same value = 100 behind the scene, but this is not what I asked the method to give me.

Any ideas on how to get the proper description attribute in this case ( Besides changing the intrinsic enum value ) ? I don't see any method overloads that would help me in that scope..

Thanks for shedding some light.

Upvotes: 1

Views: 140

Answers (1)

DavidG
DavidG

Reputation: 118987

Remember that enums are really just glorified integers. So when you pass in LambdaPackageError.BaseError0, that resolves to 100 which becomes LambdaPackageError.__packageOffset or LambdaPackageError.__base_offset (I'm not sure what the rules are for which one is actually chosen)

It looks like you are using the offsets as a base values to start your enum values at but I suspect you don't use that elsewhere in code. So instead I would suggest moving that value out as a private const values, for example:

private const int __packageOffset = 100;
private const int __base_offset = __packageOffset;
private const int __extended_offset = __packageOffset + 10;

public enum LambdaPackageError : int
{
    [Description("Base error 0")]
    BaseError0 = __base_offset,
    [Description("Base error 1")]
    BaseError1 = __base_offset + 1,
    [Description("Base error 2")]
    BaseError2 = __base_offset + 2,

    // extended errors
    [Description("Extended error 0")]
    ExtendedError0 = __extended_offset,
    [Description("Extended error 1")]
    ExtendedError1 = __extended_offset + 1
}

Upvotes: 1

Related Questions