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:
- Specify serialization information for a class.
- Mark a method as obsolete and provide a replacement.
- Define a web service endpoint for a method.
- Control the behavior of a compiler or runtime environment.
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));
}
}
Commonly Used Attributes
The .NET Framework includes many built-in attributes. Some common ones include:
[Serializable]
: Indicates that a class can be serialized.[Obsolete]
: Marks a code element as obsolete.[Serializable]
: Indicates that a class can be serialized.[STAThread]
/[MTAThread]
: Specifies the threading model for a managed application.[Conditional]
: Specifies that a method call should be ignored under certain preprocessor symbols.
Custom Attributes
You can create your own custom attributes by deriving from System.Attribute
and applying the [AttributeUsage]
attribute to your custom attribute class.