Attribute sind in C# eine Möglichkeit, deklarative Metadaten an Code-Elemente anzuheften: Klassen, Methoden, Properties, Parameter, Felder, Assemblies. Ein Attribut ist technisch eine Klasse, die von System.Attribute abgeleitet ist; es wird in eckigen Klammern direkt vor dem zu annotierenden Element platziert, etwa Obsolete, Required, HttpGet oder JsonPropertyName.
Eingesetzt werden Attribute in nahezu jedem .NET-Framework: in ASP.NET Core für Routing und Modellbindung (Route, HttpPost, FromBody), in Validierungs-Frameworks (Required, Range, StringLength), in Serialisierern (Json- und XML-Attribute), in Test-Frameworks (Fact, Test, TestMethod, Theory), in Entity Framework (Key, Column), in Source Generators und Roslyn Analyzers sowie in Sicherheits- und Telemetrie-Frameworks.
Der Einsatzzweck und das gelöste Problem liegen in der Trennung zwischen Verhalten und Konfiguration. Attribute machen es möglich, an einer einzigen Stelle (am Code-Element) Aspekte wie ‚dieses Feld ist obligatorisch', ‚dieser Endpunkt mappt auf POST /orders', ‚dieser Test ist Teil einer Theorie' deklarativ zu beschreiben, ohne dafür Frameworks-Code in der Geschäftslogik zu vermischen. Frameworks lesen diese Attribute zur Laufzeit (über Reflection) oder zur Compile-Zeit (über Source Generators) und implementieren das passende Verhalten.
Historisch sind Attribute seit C# 1.0 (2002) Teil der Sprache und an analoge Konzepte aus früheren Sprachfamilien angelehnt — etwa die Custom Attributes in C++/CLI oder die Annotationen in Java (eingeführt 2004 mit Java 5). Mit C# 12 (2023) sind Attribute auf Lambdas und Primary Constructors möglich, und mit Generic Attributes (C# 11) können Attribut-Typen jetzt selbst generisch sein, was insbesondere für Source-Generator-basierte Frameworks neue Möglichkeiten eröffnet.
Eingeführt wurden Attribute durch Microsoft und das .NET-Designteam um Anders Hejlsberg. In den ersten Jahren hatten Attribute den Ruf, ‚magisch' und schwer zu testen zu sein, weil das tatsächliche Verhalten nicht im annotierten Code, sondern im Framework-Code lag, das sie las. Über die Jahre hat sich daraus ein bewusster Architekturstil entwickelt: ‚Attribute beschreiben Intention, Code beschreibt Mechanik'. Insbesondere ASP.NET Core hat dieses Modell so weit getrieben, dass eine vollständige Web-API mit nur wenigen Attributen, einer Routendeklaration und Minimal-APIs vollständig deklarativ definiert werden kann.