Код, понятный IDE и AI: использование атрибутов из JetBrains.Annotations
У JetBrains есть фреймворк JetBrains.Annotations для .NET, который предоставляет набор полезных атрибутов. Они выступают дополнительными метаданными как для самих разработчиков, так и для статического анализатора JB, который включён в их IDE и ReSharper.
JetBrains.Annotations доступен в nuget, но может ограниченно работать вне продуктов JetBrains. Тем не менее в System.Diagnostics.CodeAnalysis тоже есть набор стандартных полезных и похожих атрибутов.
В первую очередь, атрибуты позволяют лучше понимать как намерения автора, так логику и семантику кода, а не только его синтаксис. Это делает листинг проще (если не переборщить с обилием атрибутов) и позволяет анализатору максимально своевременно предупредить разработчика или дать ему подсказку.
В текущих реалиях у этих атрибутов появилось ещё одно полезное свойство – они учитываются нейросетью и помогают ей быстрее ориентироваться в проекте. И, как мне показалось, автокомплит тоже становится более точным (про инструменты, доступные в Rider, делал отдельную, ещё не сильно устаревшую, подборку).
Важно отметить, что атрибуты — это лишь мета-информация для анализатора, которая не влияет на runtime.
Например, использование атрибута [NotNull] для аргумента метода не добавляет автоматической проверки. В метод всё ещё можно будет передать null. И если в методе этот кейс не будет обработан, то случится NullReferenceException. Атрибут лишь подскажет IDE, что в этот метод не нужно позволять передавать null на этапе разработки.
Также важно отметить, что этот фреймворк развивается давно, а языки программирования не стоят на месте. Поэтому какие-то атрибуты для определённых версий языка могут оказаться избыточными. Так, например, появление nullable reference type в C# 8 позволяет выразить намерения по null-спецификациям средствами самого языка.
Про этот кейс, атрибуты от JB и MS, операторы ? и !, когда что и для чего использовать, можно подробнее почитать в этом лонгриде с Хабра.
Ещё один нюанс связан с тем, что для Unity-проектов атрибуты Jetbrains поддерживаются по умолчанию, но не в полном объёме. Так, например, не удастся применить [NonNegativeValue] или [ValueRange]. В теории, можно выкачать более актуальный Jetbrains.Annotations из nuget и добавить в проект. Но лично у меня не было необходимости этим заниматься.
Примеры атрибутов
Всем, кто работает с инструментами JB, рекомендую ознакомиться с полным списком атрибутов. А здесь оставлю наиболее часто встречаемые и работающие в Unity.
⚠ Дисклеймер ⚠
Далее будет сгенерированный код.
Особо чувствительным лучше остановиться здесь.
Код проверен, исправлен, дополнен комментариями.