1. Основные модификаторы доступа в C#
Когда вы пишете программу, часто хочется чётко контролировать, кто и откуда может видеть или изменять ваши переменные и вызывать методы. Это как в многоквартирном доме: не все помещения открыты для всех. К одним доступ есть только у жильцов, а к другим — только у специалистов по обслуживанию.
В программировании этот "контроль доступа" решается через модификаторы доступа. Они определяют, виден ли член класса (переменная, поле, метод, свойство и т.д.) вне класса, в другом классе, в другом проекте. Это и есть одна из главных реализаций инкапсуляции в ООП: мы скрываем детали реализации, предоставляя только нужные наружу "интерфейсы".
Вот табличка с основными модификаторами и кратким описанием:
| Модификатор | Где видно? (на пальцах) |
|---|---|
|
Везде (в рамках проекта и вне его — если есть сборка) |
|
Только внутри того же класса |
|
То же, что и private |
Выглядит страшно? На самом деле здесь нет ничего сложного. Давайте разберёмся на примерах, где какой лучше использовать.
2. Модификатор public — ходи, кто хочешь
Модификатор public делает вашу переменную или метод видимым везде. Если вы объявили член класса public, то к нему можно обратиться из любого другого кода, который видит ваш класс.
public class Person
{
public string Name;
public void SayHello()
{
Console.WriteLine($"Привет! Меня зовут {Name}");
}
}
Теперь где угодно (в том же проекте или даже в других, если добавить ссылку на сборку), можно написать:
Person p = new Person();
p.Name = "Алиса";
p.SayHello();
Практический совет: не стоит делать всё подряд public: это ключ к безопасности кода.
3. Модификатор private — это частная собственность!
Модификатор private закрывает доступ к содержимому класса: никто снаружи не увидит, что там, и не изменит данные. По умолчанию все поля и методы классов в C# — private, если вы не указали другой модификатор.
public class Cup
{
private double volume; // Это поле видит только сам класс Cup
public void Fill(double value)
{
volume = value; // Можно использовать внутри класса
}
public double GetVolume()
{
return volume; // Но снаружи никто не узнает, что volume есть
}
}
Здесь volume скрыт от всех остальных, но использовать его может любой метод внутри Cup. Чтобы узнать объем, мы предоставляем публичный метод GetVolume().
4. Область видимости: переменные, методы и классы
Область видимости — это зона программы, где ваше имя (переменная, метод, класс) имеет смысл и доступно.
- Локальные переменные (объявлены внутри метода или блока кода): видны только в этом методе или блоке.
- Параметры методов: видны только внутри метода.
- Поля класса: видны везде в пределах класса (с учётом модификатора доступа).
- Классы: вложенный класс виден только в классе-обёртке, если он private, и т.д.
Посмотрим на пример с областью видимости:
public class Counter
{
private int count = 0; // видно везде в классе
public void Increment()
{
count++; // можем использовать поле
int temp = count * 2; // temp виден только внутри Increment
}
public int GetCount()
{
// temp здесь не виден!
return count;
}
}
Если попытаетесь обратиться к temp внутри GetCount() — получите ошибку.
5. Затенение переменных (shadowing)
Затенение — это ситуация, когда в одной области видимости объявляется переменная (или параметр) с тем же именем, что и во внешней области. Внутри этого блока “новое” имя затеняет старое, и к внешнему значению уже нельзя обратиться напрямую.
Пример затенения:
class ShadowDemo
{
int value = 10; // поле класса
void PrintValue()
{
Console.WriteLine(value); // 10 — поле класса
int value = 5; // локальная переменная затеняет поле класса
Console.WriteLine(value); // выведет 5, а не 10
}
}
В данном примере, когда мы пишем int value = 5;, это затеняет поле класса с тем же именем внутри метода. При обращении к value внутри PrintValue(), будет использована локальная переменная, а не поле класса.
Если всё-таки нужно обратиться к полю класса, используется ключевое слово this:
class ShadowDemo
{
int value = 10;
void PrintValue()
{
Console.WriteLine(value); // 10 — поле класса
int value = 5;
Console.WriteLine(value); // 5 — локальная переменная
Console.WriteLine(this.value); // 10 — поле класса
}
}
Затенение может запутывать, поэтому рекомендуется давать переменным осмысленные, разные имена — особенно если вы работаете в больших командах.
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ