C# Attributes
An attribute is a marker that attaches metadata to a type or a member. A program reads the markers back at runtime with reflection.
Flags on an enum
The [Flags] marker lets enum values combine with the | operator. A combined value prints every flag it contains.
using System;
[Flags]
enum Access
{
None = 0,
Read = 1,
Write = 2,
Run = 4
}
class Program
{
static void Main(string[] args)
{
Console.WriteLine(Access.Read);
Console.WriteLine(Access.Read | Access.Write);
}
}Reading a marker back
IsDefined reports whether a type carries a given attribute. A marked class returns true and an unmarked class returns false.
using System;
using System.Reflection;
[Serializable]
class Record
{
public int Id;
}
class Plain
{
public int Id;
}
class Program
{
static void Main(string[] args)
{
Console.WriteLine(typeof(Record).IsDefined(typeof(SerializableAttribute), false));
Console.WriteLine(typeof(Plain).IsDefined(typeof(SerializableAttribute), false));
}
}The Obsolete marker
A class can carry [Obsolete] without ever being created. IsDefined confirms the marker is stored on the type.
using System;
using System.Reflection;
[Obsolete("Use NewTool instead")]
class OldTool
{
public int Level;
}
class Program
{
static void Main(string[] args)
{
Console.WriteLine(typeof(OldTool).IsDefined(typeof(ObsoleteAttribute), false));
}
}Example
using System;
using System.Reflection;
[Flags]
enum Permissions
{
None = 0,
View = 1,
Edit = 2,
Share = 4
}
class Program
{
static void Main(string[] args)
{
Console.WriteLine(Permissions.View | Permissions.Edit);
Console.WriteLine(typeof(Permissions).IsDefined(typeof(FlagsAttribute), false));
}
}Key points
- An attribute sits in square brackets directly above the type or member it marks.
- The [Flags] attribute changes how an enum prints and marks its values as combinable bits.
- Each [Flags] enum value takes a power of two, so combined values stay unique.
- The [Serializable] attribute is a pure marker with no data of its own.
- Type.IsDefined checks whether a marker is present and returns a bool.
- The [Obsolete] attribute warns at call sites when marked code is used.
In this example, the Permissions enum carries the [Flags] marker. Main combines View and Edit with the | operator. The combined value prints both flag names. IsDefined then confirms the FlagsAttribute marker sits on the enum.
Note
The Obsolete warning is a compiler warning, not an error, and marked code still compiles.
Try it Yourself
Edit the code, then press Run.
Running is simulated
Exercise
What does Type.IsDefined report?