C# Attributes
Attributes in C# are a powerful mechanism for adding declarative metadata to code elements. They provide a way to associate extra information with types, methods, properties, fields, and other program entities. This metadata can then be examined at runtime using reflection, or at compile time by attribute-aware tools.
What are Attributes?
An attribute is a declarative tag that can be applied to any code construct (assemblies, classes, methods, properties, etc.). Attributes themselves are classes that inherit from the System.Attribute base class. They are typically used to modify the behavior of code or to provide information to tools and the .NET runtime.
Using Attributes
Attributes are applied using square brackets ([]) before the code element they are decorating. The attribute's name can be specified with or without the Attribute suffix. For example, [Serializable] is equivalent to [SerializableAttribute].
Commonly Used Built-in Attributes
C# and the .NET Framework provide a rich set of built-in attributes:
[Serializable]: Indicates that a class can be serialized.[Obsolete]: Marks a code element as obsolete and optionally provides a message about its replacement.[AttributeUsage]: Specifies how an attribute can be used (e.g., on which code elements it can be applied).[Conditional]: Allows a method to be included or excluded from compilation based on a preprocessor symbol.[DllImport]: Used to import functions from unmanaged dynamic-link libraries (DLLs).
Creating Custom Attributes
You can create your own attributes by defining a class that inherits from System.Attribute.
Example: Creating a simple custom attribute
using System;
[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 MyClass
{
[MyCustom("This is a sample method.")]
public void MyMethod()
{
Console.WriteLine("Hello from MyMethod!");
}
}
Attribute Usage and Targets
The [AttributeUsage] attribute is used to control where your custom attribute can be applied. The AttributeTargets enumeration specifies the valid targets:
AssemblyClassStructEnumConstructorMethodPropertyFieldEventInterfaceParameterDelegateAll
You can also specify the AllowMultiple and Inherited parameters within [AttributeUsage].
Retrieving Attribute Information (Reflection)
Attributes are most powerful when combined with reflection, which allows you to inspect metadata at runtime.
Example: Retrieving custom attribute information
using System;
using System.Reflection;
// ... (MyCustomAttribute and MyClass definitions from above)
public class AttributeReader
{
public static void InspectAttributes(Type type)
{
Console.WriteLine($"Inspecting type: {type.Name}");
// Check for attributes on the class
object[] classAttributes = type.GetCustomAttributes(typeof(MyCustomAttribute), false);
foreach (MyCustomAttribute attr in classAttributes)
{
Console.WriteLine($"- Class Attribute: {attr.Description}");
}
// Check for attributes on methods
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)
{
InspectAttributes(typeof(MyClass));
}
}
Output:
Inspecting type: MyClass
- Class Attribute: This is a sample class.
- Method 'MyMethod' Attribute: This is a sample method.
Use Cases for Attributes
- Serialization: Controlling how objects are serialized (e.g.,
[Serializable],[XmlElement]). - Code Generation: Providing information for code generators (e.g., ORMs like Entity Framework).
- Runtime Configuration: Storing configuration settings or metadata that influences runtime behavior.
- Unit Testing: Marking test methods or classes (e.g., in frameworks like NUnit or xUnit).
- API Documentation: Adding metadata for documentation generators (e.g., XML documentation comments).
- Framework Integration: Used extensively by frameworks like ASP.NET MVC (e.g.,
[HttpGet],[Route]) and WCF.
Note: Attributes are purely declarative. They do not change the behavior of the code element they are attached to unless that code element's behavior is specifically designed to inspect and act upon those attributes (e.g., via reflection).