Атрибуты в C#: метаданные, предопределённые и пользовательские атрибуты
Что такое атрибуты
Атрибут (Attribute) — декларативная метка (метаданные), добавляемая к программным элементам (классы, методы, свойства, поля, сборки, параметры и др.). Синтаксис: квадратные скобки над элементом [AttributeName].
Атрибуты не влияют на логику выполнения напрямую — их считывают инструменты, компилятор или код во время выполнения через рефлексию.
Синтаксис применения
[AttributeName(позиционные_параметры, ИменованныйПараметр = значение)]
public class MyClass { }
- Позиционные параметры — соответствуют параметрам конструктора атрибута (обязательные)
- Именованные параметры — соответствуют публичным полям/свойствам атрибута (опциональные)
Предопределённые атрибуты (.NET Framework)
1. [Obsolete] — устаревший член
[Obsolete("Use NewMethod instead", true)] // true = ошибка компиляции
public void OldMethod() { }
[Obsolete("Deprecated")] // false = предупреждение
public void LegacyMethod() { }
2. [Conditional("SYMBOL")] — условный вызов метода
Вызов метода включается в IL только если символ определён. Идеально для логирования/диагностики.
#define DEBUG
using System.Diagnostics;
public class Logger
{
[Conditional("DEBUG")]
public static void Log(string msg) => Console.WriteLine($"[DEBUG] {msg}");
}
Logger.Log("Started"); // В Release (без DEBUG) вызова НЕТ в скомпилированном коде
3. [AttributeUsage] — настройка пользовательского атрибута
[AttributeUsage(
AttributeTargets.Class | AttributeTargets.Method | AttributeTargets.Property,
AllowMultiple = true, // можно применять несколько раз
Inherited = false // не наследуется производными классами
)]
public class MyAttribute : Attribute { }
AttributeTargets: All, Class, Struct, Enum, Interface, Delegate, Method, Property, Field, Parameter, Constructor, Event, Assembly, Module, ReturnValue, GenericParameter.
Создание пользовательских атрибутов
- Наследуйтесь от
System.Attribute - Добавьте
[AttributeUsage] - Реализуйте конструктор(ы) для позиционных параметров
- Добавьте свойства для именованных параметров
Пример: атрибут отладки
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method | AttributeTargets.Property,
AllowMultiple = true)]
public class DebugInfoAttribute : Attribute
{
public int BugNumber { get; }
public string Developer { get; }
public string LastReview { get; }
public string Message { get; set; } // именованный параметр
public DebugInfoAttribute(int bugNo, string developer, string lastReview)
{
BugNumber = bugNo;
Developer = developer;
LastReview = lastReview;
}
}
// Применение
[DebugInfo(45, "Zara Ali", "12/08/2024", Message = "Return type mismatch")]
[DebugInfo(49, "Nuha Ali", "10/10/2024", Message = "Unused variable")]
public class Rectangle
{
public double Length { get; set; }
public double Width { get; set; }
[DebugInfo(55, "Zara Ali", "19/10/2024", Message = "Return type mismatch")]
public double GetArea() => Length * Width;
[DebugInfo(56, "Zara Ali", "19/10/2024")]
public void Display() { ... }
}
Чтение атрибутов через рефлексию
Type type = typeof(Rectangle);
// Атрибуты класса
foreach (var attr in type.GetCustomAttributes())
{
Console.WriteLine($"Bug: {attr.BugNumber}, Dev: {attr.Developer}, Review: {attr.LastReview}, Msg: {attr.Message}");
}
// Атрибуты методов
foreach (var method in type.GetMethods())
{
foreach (var attr in method.GetCustomAttributes())
{
Console.WriteLine($"Method {method.Name}: Bug {attr.BugNumber}");
}
}
Популярные атрибуты из BCL
| Атрибут | Назначение |
|---|---|
[Serializable] | Класс можно сериализовать (BinaryFormatter, устарел) |
[DataContract] / [DataMember] | WCF/JSON сериализация |
[JsonPropertyName] | System.Text.Json имя свойства |
[Required], [StringLength] | Валидация (DataAnnotations) |
[DllImport] | P/Invoke вызов нативной DLL |
[CallerMemberName], [CallerFilePath], [CallerLineNumber] | Автозаполнение информации о вызывающем коде |
[DoesNotReturn], [NotNull], [MaybeNull] | Nullable-анализ (C# 8+) |
[MethodImpl(MethodImplOptions.AggressiveInlining)] | Подсказка JIT |
Атрибуты сборки (assembly-level)
В файле AssemblyInfo.cs или Program.cs (современные шаблоны):
[assembly: AssemblyTitle("MyApp")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0-beta.1")]
[assembly: InternalsVisibleTo("MyApp.Tests")] // доступ к internal для тестов
Язык C
- Освоение Java 8 Optional: Практическое руководство по коду, безопасному для null
- Nullable-типы в C#: безопасная работа со значениями null
- Ferro-Titanit® Cromoni — высокопрочный неметаллический титановый сплав
- Сплав AgCu20: Механические, тепловые и электрические свойства при 23 °C
- Сплав 15CDV6 (DIN 1.7734): Высокая прочность, вязкость и легкая сварка
- Сплав DIN 1.7734 (15CDV6): Высокая прочность, вязкость и свариваемость
- Сплав 15CDV6 (DIN 1.7734): Высокая прочность, легкая сварка, превосходная вязкость
- Сплав PtNi10 – Комплексные механические и тепловые свойства
- Сплав PtIr10 платина-иридий: высокопрочный материал для высоких температур
- Лист Corroplast – Коррозионно-стойкая сталь для точной обработки и формообразования