Ответ
В C# существует шесть модификаторов доступа, которые определяют область видимости и доступность типов (классов, структур, интерфейсов) и их членов (полей, свойств, методов).
| Модификатор | Доступность | Область применения по умолчанию |
|---|---|---|
public |
Не ограничена. Доступен из любого кода в той же сборке (assembly) или в других сборках, которые на нее ссылаются. | Члены интерфейса, перечисления. |
private |
Доступен только внутри объявляющего типа (класса или структуры). | Члены класса и структуры. |
protected |
Доступен внутри объявляющего типа и во всех производных (наследующих) классах. Производный класс может находиться в другой сборке. | - |
internal |
Доступен из любого кода в той же сборке, но не из других сборок. | Типы (классы, структуры) без явного модификатора. |
protected internal |
Объединение protected ИЛИ internal. Доступен: 1) из кода в той же сборке, 2) из производных классов (даже в других сборках). |
- |
private protected (C# 7.2+) |
Пересечение protected И internal. Доступен только из производных классов, которые находятся в той же сборке. |
- |
Практические примеры и сценарии использования:
// Файл: AssemblyA.dll
public class BaseClass
{
public int PublicField; // Виден всем.
private int _privateField; // Виден только внутри BaseClass.
protected int ProtectedField; // Виден в BaseClass и DerivedClass (даже в другом DLL).
internal int InternalField; // Виден во всей AssemblyA.dll.
protected internal int ProtIntField; // Виден в AssemblyA.dll И в DerivedClass из любого DLL.
private protected int PrivProtField; // Виден ТОЛЬКО в BaseClass и DerivedClass внутри AssemblyA.dll.
}
internal class InternalClass { } // Класс виден только внутри AssemblyA.dll.
// Файл: AssemblyB.dll (ссылается на AssemblyA.dll)
public class DerivedClass : BaseClass
{
public void Demo()
{
PublicField = 1; // OK
// _privateField = 2; // ОШИБКА: недоступно
ProtectedField = 3; // OK (наследование)
// InternalField = 4; // ОШИБКА: другая сборка
ProtIntField = 5; // OK (наследование работает)
// PrivProtField = 6; // ОШИБКА: другая сборка (нарушено условие "private protected")
}
}
// В другом классе AssemblyB.dll
class AnotherClass
{
void Demo()
{
var obj = new BaseClass();
obj.PublicField = 1; // OK
// obj.ProtectedField = 2; // ОШИБКА: нет наследования
// obj.InternalField = 3; // ОШИБКА: другая сборка
// obj.ProtIntField = 4; // ОШИБКА: другая сборка И нет наследования
}
}
Рекомендации:
- Соблюдайте принцип минимального доступа: начинайте с
privateи расширяйте видимость только при необходимости. publicинтерфейс класса должен быть минимальным и стабильным.- Используйте
internalдля скрытия служебных типов и методов, которые не должны быть частью публичного API вашей библиотеки. private protectedполезен в больших проектах для создания "семейного" доступа внутри одной сборки.
Видео-ответы
▶
▶
▶
▶
▶
▶
▶