Чем отличаются модификаторы доступа public, private, protected и internal в C#?
Постоянно путаюсь в модификаторах доступа. public и private более-менее понятны, а вот protected и internal — нет. Можете объяснить разницу с примерами?
class Account
{
public decimal Balance;
private string pin;
protected int id;
internal bool isActive;
}
2 ответа
Модификаторы доступа определяют, откуда виден член. По возрастанию открытости:
| Модификатор | Доступ |
|---|---|
private |
только внутри этого же класса |
protected |
внутри класса и его наследников |
internal |
внутри той же сборки (проекта/DLL) |
protected internal |
наследники ИЛИ та же сборка |
private protected |
наследники И только в той же сборке |
public |
отовсюду |
На примере:
class Account
{
public decimal Balance; // видно всем
private string pin; // только внутри Account
protected int id; // в Account и наследниках
internal bool isActive; // во всём проекте, но не из чужой DLL
}
class SavingsAccount : Account
{
void Demo()
{
id = 5; // OK — protected, мы наследник
Balance = 100; // OK — public
// pin = "1234"; // ОШИБКА — private, недоступно даже наследнику
}
}
Практика: делайте поля private, а наружу открывайте только то, что действительно нужно (через public-свойства или методы). Это и есть инкапсуляция. protected — для членов, которые должны видеть потомки. internal — для деталей реализации внутри библиотеки, скрытых от внешних пользователей.
По умолчанию (если модификатор не указан) члены класса — private, а сами классы — internal.
Чтобы запомнить internal: представьте, что вы пишете библиотеку (NuGet-пакет). То, что public, увидят пользователи пакета. То, что internal, — только код внутри вашей сборки, для пользователей это невидимо. Так вы прячете внутреннюю кухню, оставляя чистый публичный API.
public class Calculator // часть публичного API
{
public int Add(int a, int b) => Helper.Sum(a, b);
}
internal static class Helper // деталь реализации, снаружи не видна
{
public static int Sum(int a, int b) => a + b;
}