How to create your own custom attributes in C#

Custom attributes in C# can be used to add metadata or additional information to our code elements, such as classes, methods, and properties. It allows us to add runtime and user-defined properties to our code annotations that can be inspected and used. Custom attributes are a form of declarative programming, providing a means to describe additional information about code elements without directly affecting the code’s behavior.

An illustration depicting a mechanism of labeling custom attributes to boxes
An illustration depicting a mechanism of labeling custom attributes to boxes

Imagine you’re a shipping company manager and have to assign certain packages with specific handling instructions. To do this, create a set of unique labels or tags that indicate the different package handling requirements. Let’s look at the steps on how we can apply the above example:

  • Custom attributes: We create custom labels or tags such as “Fragile,” “Perishable,” and “Do Not Stack.”

  • Application: These custom attributes are attached to specific packages based on their contents.

  • Instructions: Handlers can quickly identify packages marked with these custom attributes and apply appropriate care or handling procedures. For instance, a package labeled “Fragile” might need to be handled delicately, while “Perishable” packages might require expedited shipping.

Concepts and considerations

Let’s have a look at the key points about custom attributes:

  1. Declaration: Custom attributes are defined by creating custom attribute classes. These classes inherit from the System.Attribute class and can have properties, fields, or other members to store additional information.

  2. Application: We can apply custom attributes to code elements like classes, methods, properties, fields, and parameters. It is typically done by including the attribute’s name in square brackets before the code element.

  3. Metadata: Custom attributes add metadata to code, which tools, libraries, or other code at runtime can use. For example, attributes can be used for documentation generation, serialization, and validation.

  4. Reflection: We can use reflection to access the information stored in custom attributes at runtime. Reflection allows us to inspect and query attributes applied to code elements.

  5. Attribute usage: The attribute usage property can be used when defining a custom attribute to determine where it can be applied and whether it can be applied to the same code element at multiple instances.

Steps to create custom attributes

  1. Define the custom attribute class: Creates a reusable attribute to attach additional information to classes, methods, and properties. Line 1 Inherits from the Attribute class, making it a custom attribute. Line 3 has a property SomeProperty to store custom data.

public class OurCustomAttribute : Attribute
{
public string SomeProperty { get; set; }
}
  1. Apply our custom attribute: Our custom attribute can be applied to many code elements, including properties, methods, and classes. On line 1 the attribute is applied using square brackets [] before the element’s declaration. On lines 4 and 14 the SomeProperty is set with different values for each element.

[OurCustomAttribute(SomeProperty = "ClassAttribute")]
public class OurClass
{
[OurCustomAttribute(SomeProperty = "MethodAttribute")]
public void YourMethod()
{
Console.WriteLine("Executing YourMethod");
int result = AddNumbers(7, 3);
Console.WriteLine($"Result of adding numbers: {result}");
}
[OurCustomAttribute(SomeProperty = "OurPropertyAttribute")]
public string OurProperty { get; set; }
}
  1. Access custom attribute values: We can use reflection to access the values of our custom attribute at runtime. On lines 3, 15, and 27 the GetCustomAttribute method is used to retrieve the attribute instances, and the values of SomeProperty are then printed. If the attribute is not found for a particular code element, a corresponding message is printed:

Type type = typeof(OurClass);
OurCustomAttribute classAttribute = (OurCustomAttribute)type.GetCustomAttribute(typeof(OurCustomAttribute));
if (classAttribute != null)
{
string propertyValue = classAttribute.SomeProperty;
Console.WriteLine($"Class Attribute: {propertyValue}");
}
else
{
Console.WriteLine("Class Attribute not found.");
}
MethodInfo methodInfo = type.GetMethod("YourMethod");
OurCustomAttribute methodAttribute = (OurCustomAttribute)methodInfo.GetCustomAttribute(typeof(OurCustomAttribute));
if (methodAttribute != null)
{
string methodValue = methodAttribute.SomeProperty;
Console.WriteLine($"Method Attribute: {methodValue}");
}
else
{
Console.WriteLine("Method Attribute not found.");
}
PropertyInfo propertyInfo = type.GetProperty("OurProperty");
OurCustomAttribute propertyAttribute = (OurCustomAttribute)propertyInfo.GetCustomAttribute(typeof(OurCustomAttribute));
if (propertyAttribute != null)
{
string propertyValue = propertyAttribute.SomeProperty;
Console.WriteLine($"Property Attribute: {propertyValue}");
}
else
{
Console.WriteLine("Property Attribute not found.");
}

Code example

Let’s take a look at the code example on how we can use custom attributes to annotate our code elements with additional metadata and then use reflection to access and utilize that metadata at runtime.

using System;
using System.Reflection;
public class OurCustomAttribute : Attribute
{
public string SomeProperty { get; set; }
}
[OurCustomAttribute(SomeProperty = "ClassAttribute")]
public class OurClass
{
[OurCustomAttribute(SomeProperty = "MethodAttribute")]
public void YourMethod()
{
Console.WriteLine("Executing YourMethod");
// Some code inside YourMethod
int result = AddNumbers(7, 3);
Console.WriteLine($"Result of adding numbers: {result}");
}
[OurCustomAttribute(SomeProperty = "OurPropertyAttribute")]
public string OurProperty { get; set; }
private int AddNumbers(int a, int b)
{
return a + b;
}
}
class Program
{
static void Main()
{
Type type = typeof(OurClass);
OurCustomAttribute classAttribute = (OurCustomAttribute)type.GetCustomAttribute(typeof(OurCustomAttribute));
if (classAttribute != null)
{
string propertyValue = classAttribute.SomeProperty;
Console.WriteLine($"Class Attribute: {propertyValue}");
}
else
{
Console.WriteLine("Class Attribute not found.");
}
MethodInfo methodInfo = type.GetMethod("YourMethod");
OurCustomAttribute methodAttribute = (OurCustomAttribute)methodInfo.GetCustomAttribute(typeof(OurCustomAttribute));
if (methodAttribute != null)
{
string methodValue = methodAttribute.SomeProperty;
Console.WriteLine($"Method Attribute: {methodValue}");
}
else
{
Console.WriteLine("Method Attribute not found.");
}
PropertyInfo propertyInfo = type.GetProperty("OurProperty");
OurCustomAttribute propertyAttribute = (OurCustomAttribute)propertyInfo.GetCustomAttribute(typeof(OurCustomAttribute));
if (propertyAttribute != null)
{
string propertyValue = propertyAttribute.SomeProperty;
Console.WriteLine($"Property Attribute: {propertyValue}");
}
else
{
Console.WriteLine("Property Attribute not found.");
}
}
}

Explanation

  • Lines 4–7: A custom attribute class OurCustomAttribute is defined, which inherits from Attribute. This custom attribute has a property SomeProperty that can be set with a string value.

  • Lines 9–29: The OurCustomAttribute is applied to different code elements:

    • It’s applied to the OurClass class, with SomeProperty set to “ClassAttribute.”

    • It’s applied to the YourMethod method, with SomeProperty set to “MethodAttribute.”

    • It’s applied to the OurProperty property, with SomeProperty set to “OurPropertyAttribute.”

  • Lines 31–72: In the Main method, the code uses reflection to retrieve and print the custom attribute values applied to the class, method, and property:

    • It obtains the type of the OurClass class.

    • It attempts to get the OurCustomAttribute applied to the class, method, and property using GetCustomAttribute.

    • If an attribute is found for a specific code element, it retrieves and prints the SomeProperty value. If an attribute is not found, it displays an appropriate message.

Free Resources

Copyright ©2025 Educative, Inc. All rights reserved