You can use the Description attribute to describe types and type members (properties, methods). One of the most common use cases is providing a user-friendly string for enum values. Here’s an example of using the Description attribute with an enum:
using System.ComponentModel;
public enum ProgrammingLanguage
{
[Description("C#")]
CSharp,
[Description("C++")]
CPlusPlus
}
Code language: C# (cs)
To read the Description attribute, use reflection and do the following steps:
- Get the type (ex: ProgrammingLanguage).
- Get the info for the member that has the Description attribute (ex: ProgrammingLanguage.CSharp).
- Get the Description attribute, and look at its value.
This can be condensed into a very long one-liner:
using System.ComponentModel;
var language = ProgrammingLanguage.CSharp;
var descriptionAttribute = language.GetType()
.GetMember(language.ToString())[0]
.GetCustomAttributes(typeof(DescriptionAttribute), inherit: false)[0] as DescriptionAttribute;
Console.WriteLine($"User picked language: {descriptionAttribute.Description}");
Code language: C# (cs)
Note: This assumes the Description attribute is present and will throw an exception if it’s not. I’ll discuss error handling further down.
This outputs the following:
User picked language: C#
Code language: plaintext (plaintext)
This approach can be used to get any attribute, not just the Description attribute.
Table of Contents
GetEnumDescription() extension method
Instead of littering your code with reflection calls, it’s often helpful to stick it in an extension method:
using System.ComponentModel;
public static class DescriptionAttributeExtensions
{
public static string GetEnumDescription(this Enum e)
{
var descriptionAttribute = e.GetType().GetMember(e.ToString())[0]
.GetCustomAttributes(typeof(DescriptionAttribute), inherit: false)[0]
as DescriptionAttribute;
return descriptionAttribute.Description;
}
}
Code language: C# (cs)
This cleans up the calling code quite a bit:
var language = ProgrammingLanguage.CSharp;
var description = language.GetEnumDescription();
Console.WriteLine($"My favorite language is : {description}");
Code language: C# (cs)
This outputs:
My favorite language is : C#
Code language: plaintext (plaintext)
Handling missing Description
The code shown so far lets exceptions bubble up. If the Description attribute is missing (or if GetMember() can’t find the member), the code shown above will throw an IndexOutOfRangeException.
There’s two other error handling approaches you can do:
- Detect errors and throw an exception with a meaningful error message.
- Return a default value if the Description attribute is missing.
Here’s an example of returning the Name if the Description attribute is missing:
public static string GetEnumDescriptionOrName(this Enum e)
{
var name = e.ToString();
var memberInfo = e.GetType().GetMember(name)[0];
var descriptionAttributes = memberInfo.GetCustomAttributes(typeof(DescriptionAttribute), inherit: false);
if (!descriptionAttributes.Any())
return name;
return (descriptionAttributes[0] as DescriptionAttribute).Description;
}
Code language: C# (cs)
Use whatever error handling approach makes sense in your specific situation.
When Description is on a property or class
Here’s an example of applying the Description attribute to property and a class:
using System.ComponentModel;
[Description("An organism that converts caffeine into code")]
public class Coder
{
public ProgrammingLanguage Language { get; set; }
[Description("Coder's full name in their culture's format")]
public string Name { get; set; }
}
Code language: C# (cs)
I’ll show how to read these below.
Property
Here’s how to get the Description attribute from the Coder.Name property:
var propertyAttribute = typeof(Coder).GetMember(nameof(Coder.Name))[0]
.GetCustomAttributes(typeof(DescriptionAttribute), inherit: false)[0]
as DescriptionAttribute;
Console.WriteLine($"Coder.Name description = {propertyAttribute.Description}");
Code language: C# (cs)
This outputs:
Coder.Name description = Coder's full name in their culture's format
Code language: plaintext (plaintext)
Class
Here’s how to get the Description attribute from the Coder class:
var classDescription = typeof(Coder)
.GetCustomAttributes(typeof(DescriptionAttribute), inherit: false)[0]
as DescriptionAttribute;
Console.WriteLine($"Coder = {propertyAttribute.Description}");
Code language: C# (cs)
This outputs:
Coder = An organism that converts caffeine into code
Code language: plaintext (plaintext)
All of the extension methods
Here’s all of the code shown in this article as extension methods:
using System;
using System.ComponentModel;
using System.Linq;
public static class DescriptionAttributeExtensions
{
public static string GetEnumDescription(this Enum e)
{
var descriptionAttribute = e.GetType().GetMember(e.ToString())[0]
.GetCustomAttributes(typeof(DescriptionAttribute), inherit: false)[0]
as DescriptionAttribute;
return descriptionAttribute.Description;
}
public static string GetEnumDescriptionOrName(this Enum e)
{
var name = e.ToString();
var memberInfo = e.GetType().GetMember(name)[0];
var descriptionAttributes = memberInfo.GetCustomAttributes(typeof(DescriptionAttribute), inherit: false);
if (!descriptionAttributes.Any())
return name;
return (descriptionAttributes[0] as DescriptionAttribute).Description;
}
public static string GetMemberDescription<T>(this T t, string memberName) where T : class
{
var memberInfo = t.GetType().GetMember(memberName)[0];
var descriptionAttribute = memberInfo.GetCustomAttributes(typeof(DescriptionAttribute), inherit: false)[0] as DescriptionAttribute;
return descriptionAttribute.Description;
}
public static string GetClassDescription<T>(this T t) where T : class
{
var descriptionAttribute = t.GetType().GetCustomAttributes(typeof(DescriptionAttribute), inherit: false)[0]
as DescriptionAttribute;
return descriptionAttribute.Description;
}
}
Code language: C# (cs)
Note: This can be generalized to work with any Attribute type.
Thanks for the very useful article and code. Just what I was looking for!
I’m glad it helped you!