๐ŸŽ“ A1Learner
๐Ÿ”
0 of 28 lessons completed

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?