Полное руководство по языку программирования С# 14 и платформе .NET 10 / Рефлексия

Атрибуты в .NET

Начальный ⏱ 3 мин чтения 👁 2 🕓 обновлено 11.08.2026

Атрибуты в .NET представляют специальные инструменты, которые позволяют встраивать в сборку дополнительные метаданные. Атрибуты могут применяться как ко всему типу (классу, интерфейсу и т.д.), так и к отдельным его частям (методу, свойству и т.д.). Основу атрибутов составляет класс System.Attribute, от которого образованы все остальные классы атрибутов. В .NET имеется множество встроенных классов атрибутов. И также мы можем создавать свои собственные классы атрибутов, которые будут определять метаданные других типов.

Допустим, нам надо проверять пользователя на соответствие некоторым возрастным ограничениям. Создадим свой атрибут, который будет хранить пороговое значение возраста, с которого разрешены некоторые действия:


class AgeValidationAttribute : Attribute
{
	public int Age { get;}
    public AgeValidationAttribute() { }
	public AgeValidationAttribute(int age) => Age = age;
}

По сути это обычный класс, унаследованный от System.Atribute. В нем определено два конструктора: с параметром и без. В качестве параметра второй конструктор атрибута принимает некий пороговый возраст и сохраняет его в свойстве.

Теперь применим его к некоторому классу:


[AgeValidation(18)]
public class Person
{
    public string Name { get;}
    public int Age { get; set; }
    public Person(string name, int age)
    {
        Name = name;
        Age = age;
    }
}

Данный класс Person применяет атрибут. Для этого имя атрибута указывается в квадратных скобках непосредственно перед определением класса. Причем суффикс Attribute указывать необязательно. Обе записи [AgeValidation(18)] и [AgeValidationAttribute(18)] будут равноправны.

Если конструктор атрибута предусматривает использование параметров (public AgeValidationAttribute(int age)), то после имени атрибута мы можем указать значения для параметров конструктора. В данном случае передается значение для параметра age. То есть фактически мы говорим, что в AgeValidationAttribute свойство Age будет иметь значение 18.

В качестве альтернативы можно использовать именованные параметры для всех свойств атрибута, если класс атрибута имеет конструктор без параметров: [AgeValidation(Age = 18)]

Теперь получим атрибут класса Person и используем его для проверки объектов данного класса:


Person tom = new Person("Tom", 35);
Person bob = new Person("Bob", 16);
bool tomIsValid = ValidateUser(tom);    // true
bool bobIsValid = ValidateUser(bob);    // false

Console.WriteLine($"Результат валидации Тома: {tomIsValid}");
Console.WriteLine($"Результат валидации Боба: {bobIsValid}");

bool ValidateUser(Person person)
{
    Type type = typeof(Person);
    // получаем все атрибуты класса Person
    object[] attributes = type.GetCustomAttributes(false);

    // проходим по всем атрибутам
    foreach (Attribute attr in attributes)
    {
        // если атрибут представляет тип AgeValidationAttribute
        if (attr is AgeValidationAttribute ageAttribute)
            // возвращаем результат проверки по возрасту
            return person.Age >= ageAttribute.Age;
    }
    return true;
}

class AgeValidationAttribute : Attribute
{
	public int Age { get;}
    public AgeValidationAttribute() { }
    public AgeValidationAttribute(int age) => Age = age;
}

[AgeValidation(18)]
public class Person
{
    public string Name { get;}
    public int Age { get; set; }
    public Person(string name, int age)
    {
        Name = name;
        Age = age;
    }
}

В данном случае в методе ValidateUser через параметр получаем некоторый объект Person и с помощью метода GetCustomAttributes вытаскиваем из типа Person все атрибуты. Далее берем из атрибутов атрибут AgeValidationAttribute при его наличии (ведь мы можем его и не применять к классу) и проверям допустимость возраста пользователя. Если пользователь прошел проверку по возрасту, то возвращаем true, иначе возвращаем false. Если атрибут не применяется, возвращаем true.

Ограничение применения атрибута

С помощью атрибута AttributeUsage можно ограничить типы, к которым будет применяться атрибут. Например, мы хотим, чтобы выше определенный атрибут мог применяться только к классам:


[AttributeUsage(AttributeTargets.Class)]
class AgeValidationAttribute : Attribute
{
//....................................
}

Ограничение задает перечисление AttributeTargets, которое может принимать еще ряд значений:

  • All: используется всеми типами

  • Assembly: атрибут применяется к сборке

  • Constructor: атрибут применяется к конструктору

  • Delegate: атрибут применяется к делегату

  • Enum: применяется к перечислению

  • Event: атрибут применяется к событию

  • Field: применяется к полю типа

  • Interface: атрибут применяется к интерфейсу

  • Method: применяется к методу

  • Property: применяется к свойству

  • Struct: применяется к структуре

С помощью логической операции ИЛИ можно комбинировать эти значения. Например, пусть атрибут может применяться к классам и структурам: [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct)]

Проверь себя

📋 Тест по теме «Атрибуты в .NET» Тест по теме

Практические задания

Лёгкое Ручная проверка Заполните пропуск в коде (1)
+10 XP

В приведённом ниже фрагменте кода из этого урока пропущено одно слово. Определите его и впишите в поле ответа (без кавычек и пробелов).

class _____ : Attribute
{
	public int Age { get;}
    public AgeValidationAttribute() { }
	public AgeValidationAttribute(int age) => Age = age;
}
Войдите, чтобы отправить решение
Лёгкое Ручная проверка Заполните пропуск в коде (2)
+10 XP

В приведённом ниже фрагменте кода из этого урока пропущено одно слово. Определите его и впишите в поле ответа (без кавычек и пробелов).

[AgeValidation(_____)]
public class Person
{
    public string Name { get;}
    public int Age { get; set; }
    public Person(string name, int age)
    {
        Name = name;
        Age = age;
    }
}
Войдите, чтобы отправить решение
Лёгкое Ручная проверка Заполните пропуск в коде (3)
+10 XP

В приведённом ниже фрагменте кода из этого урока пропущено одно слово. Определите его и впишите в поле ответа (без кавычек и пробелов).

Person tom = _____ Person("Tom", 35);
Person bob = new Person("Bob", 16);
bool tomIsValid = ValidateUser(tom);    // true
bool bobIsValid = ValidateUser(bob);    // false

Console.WriteLine($"Результат валидации Тома: {tomIsValid}");
Console.WriteLine($"Результат валидации Боба: {bobIsValid}");

bool ValidateUser(Person person)
{
    Type type = typeof(Person);
    // получаем все атрибуты класса Person
    object[] attributes = type.GetCustomAttributes(false);

    // проходим по всем атрибутам
    foreach (Attribute attr in attributes)
    {
        // если атрибут представляет тип AgeValidationAttribute
        if (attr is AgeValidationAttribute ageAttribute)
            // возвращаем результат проверки по возрасту
            return person.Age >= ageAttribute.Age;
    }
    return true;
}

class AgeValidationAttribute : Attribute
{
	public int Age { get;}
    public AgeValidationAttribute() { }
    public AgeValidationAttribute(int age) => Age = age;
}

[AgeValidation(18)]
public class Person
{
    public string Name { get;}
    public int Age { get; set; }
    public Person(string name, int age)
    {
        Name = name;
        Age = age;
    }
}
Войдите, чтобы отправить решение
Лёгкое Ручная проверка Заполните пропуск в коде (4)
+10 XP

В приведённом ниже фрагменте кода из этого урока пропущено одно слово. Определите его и впишите в поле ответа (без кавычек и пробелов).

[_____Usage(AttributeTargets.Class)]
class AgeValidationAttribute : Attribute
{
//....................................
}
Войдите, чтобы отправить решение
Лёгкое Ручная проверка Заполните пропуск в коде (5)
+10 XP

В приведённом ниже фрагменте кода из этого урока пропущено одно слово. Определите его и впишите в поле ответа (без кавычек и пробелов).

class _____ValidationAttribute : Attribute
{
	public int Age { get;}
    public AgeValidationAttribute() { }
	public AgeValidationAttribute(int age) => Age = age;
}
Войдите, чтобы отправить решение
Среднее Ручная проверка Восстановите код по памяти (1)
+20 XP

В этом фрагменте кода урока пропущены два ключевых элемента. Впишите оба пропущенных значения через запятую в порядке появления (например: x, 5).

class AgeValidation_____ : Attribute
{
	public int Age { get;}
    public AgeValidationAttribute() { }
	public AgeValidationAttribute(int _____) => Age = age;
}
Войдите, чтобы отправить решение
Среднее Ручная проверка Восстановите код по памяти (2)
+20 XP

В этом фрагменте кода урока пропущены два ключевых элемента. Впишите оба пропущенных значения через запятую в порядке появления (например: x, 5).

[_____(18)]
public class Person
{
    public string Name { get;}
    public int Age { get; _____; }
    public Person(string name, int age)
    {
        Name = name;
        Age = age;
    }
}
Войдите, чтобы отправить решение
Среднее Ручная проверка Расставьте строки кода в правильном порядке
+20 XP

Строки кода из примера этого урока перемешаны. Впишите их в правильном порядке, каждую строку — с новой строки.

class AgeValidationAttribute : Attribute
}
	public AgeValidationAttribute(int age) => Age = age;
    public AgeValidationAttribute() { }
	public int Age { get;}
{
Войдите, чтобы отправить решение
Сложное Ручная проверка Объясните и модифицируйте пример из урока «Атрибуты в .NET»
+30 XP

Опишите своими словами, что делает приведённый пример кода из урока «Атрибуты в .NET», и предложите одно осмысленное изменение (например, другое входное значение или дополнительное условие). Приведите итоговый код.

class AgeValidationAttribute : Attribute
{
	public int Age { get;}
    public AgeValidationAttribute() { }
	public AgeValidationAttribute(int age) => Age = age;
}
Войдите, чтобы отправить решение
Сложное Ручная проверка Найдите потенциальную проблему в коде урока «Атрибуты в .NET»
+30 XP

Изучите приведённый фрагмент кода и опишите, при каких входных данных или условиях он может сработать не так, как ожидается (граничный случай, отсутствие проверки и т.п.). Предложите исправленный вариант.

[AgeValidation(18)]
public class Person
{
    public string Name { get;}
    public int Age { get; set; }
    public Person(string name, int age)
    {
        Name = name;
        Age = age;
    }
}
Войдите, чтобы отправить решение
Мини-проект Ручная проверка Мини-проект по теме «Атрибуты в .NET»
+50 XP

Соберите небольшую программу, которая последовательно демонстрирует ключевые идеи урока. Программа должна быть рабочей и содержать минимум два самостоятельно написанных фрагмента, а не просто копию примера из урока.

Войдите, чтобы отправить решение
Домашнее задание Ручная проверка Домашнее задание по теме «Атрибуты в .NET»
+25 XP

Напишите собственную небольшую программу, применяющую материал темы «Атрибуты в .NET». Используйте не менее одной конструкции, показанной в примерах урока. Прикрепите код решения и краткое описание того, что он делает.

Войдите, чтобы отправить решение

Обсуждение (0)

Войдите, чтобы оставить комментарий.