A Generic Approach for Bidirectional Mapping Between Enum Values and Description Attributes

Nov 23, 2025 · Programming · 7 views · 7.8

Keywords: C# | Enum | Description Attribute | Reflection | Generic Programming

Abstract: This paper provides an in-depth analysis of implementing bidirectional mapping between enum values and descriptive text using DescriptionAttribute in C#. Through examination of reflection mechanisms and generic programming, we present an efficient universal solution for retrieving enum values from descriptions, with detailed discussion on exception handling, performance optimization, and practical application scenarios.

Introduction

In modern software development, enumeration types are widely used to represent fixed sets of options. To enhance user experience, it's often necessary to provide friendly descriptive text for enum values. C#'s DescriptionAttribute offers a standardized solution for this purpose. However, in practical applications, there's frequently a need to implement the reverse operation—retrieving the corresponding enum value from descriptive text—which is particularly important for scenarios such as data binding and configuration parsing.

Problem Analysis

Consider the following enum definition example:

enum Animal
{
    [Description("")]
    NotSet = 0,

    [Description("Giant Panda")]
    GiantPanda = 1,

    [Description("Lesser Spotted Anteater")]
    LesserSpottedAnteater = 2
}

While it's straightforward to obtain descriptive text from enum values using extension methods, the reverse operation—retrieving enum values from descriptive text—lacks built-in support. This necessitates developers to implement custom parsing logic.

Core Solution

We designed a generic extension method that utilizes reflection mechanisms to achieve mapping from descriptive text to enum values:

public static class EnumEx
{
    public static T GetValueFromDescription<T>(string description) where T : Enum
    {
        foreach(var field in typeof(T).GetFields())
        {
            if (Attribute.GetCustomAttribute(field, typeof(DescriptionAttribute)) is DescriptionAttribute attribute)
            {
                if (attribute.Description == description)
                    return (T)field.GetValue(null);
            }
            else
            {
                if (field.Name == description)
                    return (T)field.GetValue(null);
            }
        }

        throw new ArgumentException("Not found.", nameof(description));
    }
}

Technical Details Analysis

Generic Constraint Design: The method employs where T : Enum constraint, ensuring that type parameters must be enum types, providing compile-time type safety.

Reflection Mechanism Application: Through typeof(T).GetFields(), all fields of the enum type are obtained, followed by using Attribute.GetCustomAttribute to check if each field contains a DescriptionAttribute.

Dual Matching Strategy: The method implements two matching modes: first attempting to match description attribute values, and if no matching description attribute is found, falling back to matching field names. This design enhances the method's fault tolerance.

Exception Handling Mechanism: When no matching item is found, the method throws ArgumentException, clearly indicating the failure reason. Developers can also modify this to return default values based on requirements.

Usage Example

The method invocation is straightforward:

var panda = EnumEx.GetValueFromDescription<Animal>("Giant Panda");

This call returns the Animal.GiantPanda enum value, achieving complete mapping from descriptive text to enum value.

Performance Considerations and Optimization

Due to the performance overhead of reflection operations, optimization in the following areas is recommended:

Application Scenario Extensions

This technique can be widely applied in:

Conclusion

The GetValueFromDescription method presented in this paper provides a complete, robust solution for bidirectional mapping of enum values. Through reasonable generic design, reflection mechanism application, and exception handling, the method maintains code simplicity while offering good extensibility and maintainability. In practical projects, developers can perform appropriate performance optimizations and functional extensions based on specific requirements.

Copyright Notice: All rights in this article are reserved by the operators of DevGex. Reasonable sharing and citation are welcome; any reproduction, excerpting, or re-publication without prior permission is prohibited.