Что такое рефлексия в C#
Что проверяют
Понимаете ли вы, что рефлексия это чтение метаданных сборки во время выполнения, и знаете ли её цену. Следом почти всегда спрашивают, где вы применяли её сами и чем заменить её в горячем коде.
Как отвечать
Каждая сборка .NET несёт метаданные о своих типах, а System.Reflection даёт к ним доступ в рантайме. Точка входа это объект Type: его получают через typeof(T), obj.GetType() или Type.GetType("Namespace.Name"). Дальше:
- исследование типов:
GetMethods(),GetProperties(),GetFields()сBindingFlags, чтобы добраться до непубличных и статических членов; - атрибуты:
GetCustomAttribute<T>(). На этом построены сериализаторы, валидация и маршрутизация в ASP.NET Core; - динамическое создание и вызов:
Activator.CreateInstance,MethodInfo.Invoke,PropertyInfo.SetValue; - загрузка сборок:
Assembly.LoadFromиAssemblyLoadContextдля плагинов.
На рефлексии работают DI-контейнеры, EF Core, AutoMapper, а xUnit находит тесты по атрибутам.
Цена: вызов через Invoke в разы медленнее прямого из-за проверок и упаковки аргументов, поэтому MethodInfo кешируют и строят из него делегат через CreateDelegate или скомпилированное дерево выражений. Второе ограничение это тримминг и Native AOT: компоновщик не видит члены, к которым обращаются по строке, и может их вырезать. Их помечают [DynamicallyAccessedMembers] или переходят на генераторы исходного кода, как в System.Text.Json.
Где спотыкаются
Говорят, что рефлексия «изменяет структуру программы». Она читает метаданные и вызывает то, что уже есть. Новый код в рантайме генерирует System.Reflection.Emit, это отдельный механизм.
Называют доступ к приватным полям «уязвимостью». private в .NET не граница безопасности, настоящая проблема в хрупкости: переименовали поле, и код упал в рантайме, а не на сборке.
Тянут Invoke в цикл на миллион итераций и не знают альтернатив. Ответ сильнее, если вы назовёте кеширование делегатов, генераторы исходного кода и UnsafeAccessor из .NET 8 для доступа к закрытым членам без рефлексии.