В каждом проекте со временем складывается архитектура: все фичи лежат по разным сборкам или собраны в более общие структурные модули (ядро, утилиты и т. д.). В некоторых случаях разработчики придерживаются строгой структуры, где каждая часть системы жёстко отделена друг от друга. Или наоборот бывает вообще одна общая сборка на весь проект.
При жесткой политике — часто надо возиться с прокидыванием ссылок на сборки. Особенно, когда разные фичи представляют из себя отдельные пакеты, каждый из которых в отдельном репозитории. Это сильно замедляет скорость разработки. Одна общая сборка — для разрастающегося проекта сулит полный бардак. Чаще всего формируется какой-то баланс, чтобы не спотыкаться о правила и не погрязнуть в болоте на длинной дистанции разработки.
Так вот, иногда хочется нарушить правила ради удобства. В наших шарпах, как мне кажется, нет одной приятной возможности, которая есть в C++. Это — дружественные методы (friend). Суть в том, что ты можешь из одного класса получить доступ к приватным членам другого класса. Ты сам помечаешь нужные тебе поля, методы или весь класс и к ним открывается доступ строго для другого указанного класса. То есть можно легально и без проблем нарушать инкапсуляцию, но только для нужных классов.
А что в C#? Такого механизма нет. Какие-то непростые пути вроде таких:
- Использовать атрибут InternalsVisibleTo к internal классу. Пример ниже, мы можем обратиться к GetValue из сборки "AnotherAssembly"
[assembly: InternalsVisibleTo("AnotherAssembly")]
namespace NotPrivateNamespace
{
internal class NotPrivate
{
private int value;
internal int GetValue() => value;
}
}- Другой способ — рефлексия, но использовать её стоит только в крайнем случае. Общий слоган способа: медленно, небезопасно, неудобно.
Где бы пригодился friend в C#?
В первую очередь для специфических задачах: инструменты редактора, утилиты разработчиков. Например, для тестирования, то есть различные "чит меню" в инспекторе. Получаешь нужный класс и без проблем прокидываешь в него данные. Игровые классы при этом остаются закрытыми и даже не знают, что кто-то вмешивается в их работу. Бонусом — никаких эдиторных инъекций (мусора), директив вроде
#if UNITY_EDITOR или public-методов, которые не нужны в продакшене.Так что в C# у тебя нет друзей. А если есть подруга — не забудь поздравить с праздником 😲
#техничка@cat_and_code