What are attributes in .NET?
Master System Design with Codemia
Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.
Introduction
In .NET, attributes are metadata objects attached to code elements such as classes, methods, properties, and assemblies. They let you describe behavior declaratively, so frameworks, tools, and your own runtime code can inspect that metadata without hard-coding special cases everywhere.
What an Attribute Really Is
An attribute in .NET is a class that derives from System.Attribute. When you apply it with square-bracket syntax, the compiler stores metadata in the assembly so it can be discovered later through reflection.
Here is a simple built-in example:
This does not change the method body. Instead, it adds metadata that the compiler and tools understand. In this case, callers get a warning because the type is marked as obsolete.
That is the core idea: attributes describe something about the code rather than directly implementing the behavior themselves.
Common Built-In Attributes
.NET uses attributes heavily across the platform. A few common examples:
- '
[Obsolete]marks APIs that should no longer be used.' - '
[Serializable]marks types that can participate in serialization workflows.' - '
[DllImport]describes interop calls into native libraries.' - '
[Flags]tells consumers that an enum is meant to be combined bitwise.'
For example, platform invocation uses metadata from DllImport:
The attribute tells the runtime how to locate the native function. Without that metadata, ordinary managed code would not know how to cross the boundary.
Creating a Custom Attribute
You can define your own attribute class when you want to annotate code with application-specific metadata.
This attribute stores a permission name. By itself, it does not enforce authorization. It only provides metadata. Some other part of the system, such as middleware or a custom framework component, must read it and act on it.
Reading Attributes with Reflection
The usual way to consume custom attributes is reflection.
This is where attributes become useful in real systems. Framework code can inspect types, methods, or parameters and change behavior based on the metadata it finds.
ASP.NET, test frameworks, serializers, and ORMs all rely heavily on this pattern.
Restricting Where an Attribute Can Be Used
AttributeUsage lets you define where your attribute is valid and whether it can be applied multiple times.
This matters because it prevents accidental misuse. If an attribute makes sense only on properties, say so explicitly instead of letting it appear on arbitrary program elements.
Common Pitfalls
- Assuming an attribute automatically changes runtime behavior. Usually, something else must read the metadata and act on it.
- Putting too much logic inside attributes themselves. Attributes should mainly carry metadata, not become mini-frameworks.
- Forgetting
AttributeUsage, which can make a custom attribute too permissive. - Using reflection-heavy attribute lookups in hot paths without caching results.
- Confusing compile-time effects, such as
[Obsolete], with runtime-inspected attributes, such as custom authorization markers.
Summary
- Attributes in .NET are metadata classes derived from
System.Attribute. - They are applied with square-bracket syntax to assemblies, types, members, and other code elements.
- Built-in attributes power features such as obsolescence warnings, interop, and serialization.
- Custom attributes let you annotate code with application-specific metadata.
- Attributes become useful when compilers, frameworks, or reflection-based code read that metadata and respond to it.

