Internal или Public? Что лучше использовать?

Я только решил задуматься о безопасности своей игры написанной на Unity. Так во-о-от...

По-сути Internal доступен из любого места моей программы также, как и public. Так что же лучше? Я везде могу вместо public поставить internal и ничего не изменится, всё также хорошо, как и раньше, будет работать.

Как я понял, public доступен даже тогда, когда игра сбилдилась, и допустим любые другие программы (к примеру читы) смогут читать и изменять любые public, не внедряясь в код и не меняя его, а internal читать и менять не смогут, если читы не внедряются в код...

В общем я запутался, прошу помочь мне разобраться в разнице между public и internal...


Ответы (3 шт):

Автор решения: Exploding Kitten

Модификаторы доступа никак не влияют на безопасность приложения (по крайней мере прямо, то как вы описали в вопросе). Т.е. даже private поля можно поменять без особых проблем, у кого будет желание - он всегда сможет это сделать.

Модификаторы доступу в основном предназначено для реализации одного из принципов ООП: инкапсуляция. Если посмотреть в Wiki, что это такое, что там есть такое описание:

Инкапсуля́ция (лат. in capsula; от capsula «коробочка») — размещение в оболочке, изоляция, закрытие чего-либо инородного с целью исключения влияния на окружающее. Например, поместить радиоактивные отходы в капсулу, закрыть кожухом механизм, убрать мешающее в ящик или шкаф.

Я специально использовал определение инкапсуляции не из программирования. Мне кажется оно более понятным для начинающих.

И в программирование это также работает. Пометив поле как public, вы сразу же разрешаете любому коду как читать, так и писать в него, что может приводить к проблемам. От простой путаницы, т.к. непонятно кто и когда поменял значение поля, до того, что просто можно сломать код.

Предположим в вашей игре есть класс:

class Game
{
    public int score; // количество очков игрока
}

// ...

var game = new Game();
game.score = 1337;

Тут видно, что можно где угодно и как угодно можно повлиять на класс, что может привести к вышеописанным проблемам. Класс - это черный ящик, у которого должна быть одна ответственность (задача которую он решает) и всем кто "смотрит" на него извне, не должны знать как он внутри работает. У них есть только публичный контракт (методы и свойства), через которые он взаимодействует с ним.

Рассмотрим следующий пример:

class Game
{
    private void AddScore() => Score++;

    public void Move()
    {
        // какая-то логика
        if (something)
            AddScore();
    }

    public int Score { get; private set; }
}

// ...

var game = new Game();
game.Score = 1337; // тут будет ошибка, т.к. мы не можем вмещаться 

У таком случае, когда кто-то пытается использовать такой код, то он может использовать метод Move, который, предположим, расчитывает логику игры и делает ход и на оставании состояния игры обновляет количество очков. Т.е. программист не пытается таким образом огранизовать безопасность всего преложения. Он просто сам себе помагает (создавая "закрытые" компоненты) и защищает (от воздействий из "внешней" среды).

→ Ссылка
Автор решения: Yotic

Чаще это нужно для библиотек, чтобы запретить использовать переменные вашей библиотеке в других проектах.
Это мало как защищает ваше приложение, только делает его более безопасным для других разработчиков.
Для защиты приложений следует задуматься над использованием sealed классов, т.к в ином случае любой человек может взять dll вашего приложения и модифицировать классы под себя.
Так например, в terraria можно было модифицировать главный класс игры и изменять часть методов. Как например, можно было запускать игру без steam и рисовать информацию об других игроках на экране.

→ Ссылка
Автор решения: Qwertiy

По сути уровни доступа нужны только ради инкапсуляции и обратной совместимости при обновлениях библиотеки (как бинарной, так и в исходниках).

Если ты не делаешь библиотеку, которую будет использовать много людей, а тем более, если ты пишешь весь код сам, можешь при сомнениях между internal и public выбирать public (а вот при разработке библиотек рекомендуют делать наоборот).

Уровни доступа по умолчанию не влияют на безопасность, поскольку с помощью рефлексии можно их полностью игнорировать. На самом деле, игнорировать можно не всегда, но ситуации, когда код, обращающийся к чему-то работает не с FullTrust на мой взгляд, крайне редки.

Упомянутый в другом ответе sealed служит примерно той же цели - в первую очередь обратная совместимость если кого-то угораздит отнаследоваться от твоего класса. Ну и немного безопасности: унаследовавшийся получит доступ к protected и сможет что-то с ним делать, но в плане безопасности это оппять же играет роль только в случае выполнения с ограниченным уровнем доверия.

→ Ссылка