Модификаторы доступа в C#: public, private, protected, internal и другие
Понимание модификаторов доступа в C#
Это руководство объясняет, как различные модификаторы доступа C# — public, private, protected, internal, protected internal и private protected — управляют видимостью типов и членов. Реальные примеры кода иллюстрируют действие каждого модификатора.
В C# модификаторы доступа определяют, кто может читать или записывать поля, вызывать методы или создавать экземпляры типов. Например:
class Student {
public string name;
private int num;
}
Здесь name виден везде, а num ограничен классом Student.
Виды модификаторов доступа
- public
- private
- protected
- internal
- protected internal
- private protected
1. Public (Публичный)
Пометка типа или члена как public делает его доступным из любого кода, ссылающегося на сборку.
using System;
namespace MyApplication {
class Student {
public string name = "Sheeran";
public void Print() {
Console.WriteLine("Hello from Student class");
}
}
class Program {
static void Main(string[] args) {
Student student1 = new Student();
Console.WriteLine("Name: " + student1.name);
student1.Print();
Console.ReadLine();
}
}
}
Вывод
Name: Sheeran Hello from Student class
Так как поле и метод public, класс Program свободно обращается к ним.
Совет: Объект student1 используется для доступа к членам Student. Подробнее о C# class and objects.
2. Private (Частный)
Член private виден только внутри своего объявляющего class или struct. Внешний код вызывает ошибки компиляции.
using System;
namespace MyApplication {
class Student {
private string name = "Sheeran";
private void Print() {
Console.WriteLine("Hello from Student class");
}
}
class Program {
static void Main(string[] args) {
Student student1 = new Student();
Console.WriteLine("Name: " + student1.name);
student1.Print();
Console.ReadLine();
}
}
}
Попытка доступа к name или Print из Program приводит к:
CS0122 'Student.name' is inaccessible due to its protection level
CS0122 'Student.Print()' is inaccessible due to its protection level
3. Protected (Защищенный)
Члены protected доступны внутри своего класса и во всех производных классах, независимо от сборки.
using System;
namespace MyApplication {
class Student {
protected string name = "Sheeran";
}
class Program : Student {
static void Main(string[] args) {
Program program = new Program();
Console.WriteLine("Name: " + program.name);
Console.ReadLine();
}
}
}
Вывод
Name: Sheeran
Здесь Program наследуется от Student, получая доступ к защищенному полю name.
4. Internal (Внутренний)
Член internal виден только внутри той же сборки — логической единицы скомпилированного кода. Сборки создаются компилятором при сборке проекта.
В пределах одной сборки:
using System;
namespace Assembly {
class Student {
internal string name = "Sheeran";
}
class Program {
static void Main(string[] args) {
Student theStudent = new Student();
Console.WriteLine("Name: " + theStudent.name);
Console.ReadLine();
}
}
}
Вывод
Name: Sheeran
Внутри одной сборки внутренний член ведет себя как public, так как internal-члены доступны во всей сборке.
В другой сборке поле недоступно:
// Assembly1
using System;
namespace Assembly1 {
public class StudentName {
internal string name = "Sheeran";
}
}
// Assembly2
using System;
using Assembly1;
namespace Assembly2 {
class Program {
static void Main(string[] args) {
StudentName student = new StudentName();
Console.Write(student.name); // CS0122
Console.ReadLine();
}
}
}
Компиляция Assembly2 дает:
CS0122 'StudentName.name' is inaccessible due to its protection level
5. Protected Internal
Комбинация protected internal разрешает доступ из той же сборки или из производных типов в других сборках.
// Assembly1
using System;
namespace Assembly1 {
public class Greet {
protected internal string msg = "Hello";
}
}
// Assembly2
using System;
using Assembly1;
namespace Assembly2 {
class Program : Greet {
static void Main(string[] args) {
Program greet = new Program();
Console.Write(greet.msg);
Console.ReadLine();
}
}
}
Вывод
Hello
6. Private Protected
Появился в C# 7.2. private protected ограничивает видимость объявляющим классом и его производными классами в той же сборке.
// Assembly1
using System;
namespace Assembly1 {
public class StudentName {
private protected string name = "Sheeran";
}
class Program1 : StudentName {
static void Main(string[] args) {
Program1 student = new Program1();
Console.Write(student.name);
Console.ReadLine();
}
}
}
// Assembly2
using System;
using Assembly1;
namespace Assembly2 {
class Program : StudentName {
static void Main(string[] args) {
Program student = new Program();
Console.Write(student.name); // CS0122
Console.ReadLine();
}
}
}
Доступ из Assembly2 не работает, так как член не экспортируется за пределы своей сборки, даже в производных типах.
Примечание: Типы (классы, интерфейсы и т.д.) могут использовать только public и internal; все остальные модификаторы применяются только к членам.
Язык C
- Классы и объекты в C#: Фундаменты надёжного ООП
- Ключевое слово static в C#: статические переменные, методы и классы
- Абстрактные классы и методы в C#: практическое руководство
- Вложенные классы в C#: определение, использование и наследование
- Частичные классы и методы в C#: понимание и применение
- Sealed-классы и sealed-методы в C#: когда использовать, примеры и повышение безопасности кода
- Шаблоны классов в C++: практическое руководство
- Классы хранения в C: область видимости, время жизни и производительность
- Модификаторы в Java: типы, применение и лучшие практики
- Полиморфизм в C++: практическое руководство