Attributes

Attributes provide a way to add declarative information to your code. This information can be accessed at runtime via reflection. Attributes are a form of metadata that can be applied to almost any code element, including classes, methods, properties, fields, and assemblies.

What are Attributes?

In C#, attributes are classes that inherit from the System.Attribute class. They are typically used to convey information about the code element to which they are attached. For example, you might use an attribute to:

Applying Attributes

Attributes are applied using square brackets ([]) immediately before the code element they modify. The attribute name can be used with or without the Attribute suffix. For example, [Serializable] is equivalent to [SerializableAttribute].

Example: Applying the Obsolete Attribute


using System;

public class OldCalculator
{
    [Obsolete("This method is obsolete. Use CalculateSum instead.")]
    public int Add(int a, int b)
    {
        return a + b;
    }

    public int CalculateSum(int a, int b)
    {
        return a + b;
    }
}
                

Attribute Targets

You can specify the valid targets for your custom attribute by using the [AttributeUsage] attribute. This helps ensure that the attribute is applied only to appropriate code elements.

Example: Defining a Custom Attribute with a Target


using System;

// Specify that this attribute can only be applied to classes and methods
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
public class MyCustomAttribute : Attribute
{
    public string Description { get; }

    public MyCustomAttribute(string description)
    {
        Description = description;
    }
}

[MyCustom("This is a sample class.")]
public class SampleClass
{
    [MyCustom("This is a sample method.")]
    public void DoSomething()
    {
        // ...
    }
}
                

Accessing Attributes via Reflection

The .NET Framework provides extensive reflection capabilities to inspect code at runtime. You can use reflection to retrieve attribute information associated with code elements.

Example: Reading Attributes using Reflection


using System;
using System.Reflection;

public class AttributeReader
{
    public static void ReadAttributes(Type type)
    {
        Console.WriteLine($"Reading attributes for type: {type.Name}");

        // Get custom attributes applied to the type
        object[] classAttributes = type.GetCustomAttributes(typeof(MyCustomAttribute), false);
        foreach (MyCustomAttribute attr in classAttributes)
        {
            Console.WriteLine($"  Class Attribute: {attr.Description}");
        }

        // Get methods and their attributes
        MethodInfo[] methods = type.GetMethods();
        foreach (MethodInfo method in methods)
        {
            object[] methodAttributes = method.GetCustomAttributes(typeof(MyCustomAttribute), false);
            foreach (MyCustomAttribute attr in methodAttributes)
            {
                Console.WriteLine($"  Method '{method.Name}' Attribute: {attr.Description}");
            }
        }
    }

    public static void Main(string[] args)
    {
        ReadAttributes(typeof(SampleClass));
    }
}
                
Note: Attributes are a powerful feature for adding metadata. They are widely used by various .NET technologies like ASP.NET, Entity Framework, and unit testing frameworks.

Commonly Used Attributes

The .NET Framework includes many built-in attributes. Some common ones include:

Custom Attributes

You can create your own custom attributes by deriving from System.Attribute and applying the [AttributeUsage] attribute to your custom attribute class.

Important: When defining custom attributes, remember that attribute constructor parameters are limited to compile-time constants. Named parameters can use a wider range of types.