理解 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# 类与对象。
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();
}
}
}
尝试从 Program 访问 name 或 Print 将报错:
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语言