跳到主要内容

C# 访问修饰符

提示
  1. 作用与应用:C# 访问修饰符定义了类、接口和其成员(如字段、方法)的可访问性,控制着从哪里可以访问这些资源。
  2. 访问修饰符种类:C# 包含四种主要访问修饰符:public(公开访问)、private(私有访问)、protected(受保护访问)、internal(程序集内访问),及其组合形式,以提供不同级别的访问控制。
  3. 使用场景示例:例如,public 类型成员可在任何地方访问,而 private 成员仅在其所在类中访问,protected 成员在其类及派生类中访问,internal 成员在同一程序集中访问。

在 C# 中,访问修饰符用于指定类型(如类、接口等)和类型成员(如字段、方法等)的可访问性。例如,

class Student {

public string name;

private int num;

}

这里,

  • name - 公共字段,可以从任何地方访问
  • num - 私有字段,只能在 Student 类内部访问

访问修饰符的类型

在 C# 中,基本上有 4 种类型的访问修饰符。

  • public
  • private
  • protected
  • internal

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 类的对象
Student student1 = new Student();

// 访问 name 字段并打印
Console.WriteLine("Name: " + student1.name);

// 从 Student 中访问 print 方法
student1.print();
Console.ReadLine();
}
}
}

输出

Name: Sheeran
Hello from Student class

在上面的示例中,我们创建了一个名为 Student 的类,其中包含字段 name 和方法 print()

// 访问 name 字段并打印
Console.WriteLine("Name: " + student1.name);

// 从 Student 中访问 print 方法
student1.print();

由于字段和方法是公开的,我们能够从 Program 类中访问它们。

注意:我们使用了 Student 类的对象 student1 来访问其成员。要了解更多,请访问 C# 类和对象

2. private 访问修饰符

当我们使用 private 访问修饰符声明一个类型成员时,它只能在相同的 classstruct 内部被访问。例如,

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 类的对象
Student student1 = new Student();

// 访问 name 字段并打印
Console.WriteLine("Name: " + student1.name);

// 从 Student 中访问 print 方法
student1.print();

Console.ReadLine();
}
}
}

在上面的示例中,我们创建了一个名为 Student 的类,其中包含字段 name 和方法 print()

// 访问 name 字段并打印
Console.WriteLine("Name: " + student1.name);

// 从 Student 类中访问 print 方法
student1.print();

由于字段和方法是私有的,我们无法从 Program 类中访问它们。这里,代码将生成以下错误。

**错误**    CS0122    'Student.name' 由于其保护级别而无法访问
**错误** CS0122 'Student.print()' 由于其保护级别而无法访问

3. protected 访问修饰符

当我们将类型成员声明为 protected 时,它只能从同一个类及其派生类中访问。例如,

using System;

namespace MyApplication {

class Student {
protected string name = "Sheeran";
}

class Program {
static void Main(string[] args) {

// 创建 Student 类的对象
Student student1 = new Student();

// 访问 name 字段并打印
Console.WriteLine("Name: " + student1.name);
Console.ReadLine();
}
}
}

在上述示例中,我们创建了一个名为 Student 的类,其中有一个字段 name。由于该字段是受保护的,我们无法从 Program 类中访问它。

这里,代码将生成以下错误。

**错误**    CS0122    'Student.name' 由于其保护级别而无法访问

现在,让我们尝试从派生类中访问 protected 成员。

using System;

namespace MyApplication {

class Student {
protected string name = "Sheeran";
}

// 派生类
class Program : Student {
static void Main(string[] args) {

// 创建派生类的对象
Program program = new Program();

// 访问 name 字段并打印
Console.WriteLine("Name: " + program.name);
Console.ReadLine();
}
}
}

输出

Name: Sheeran

在上述示例中,我们创建了一个带有受保护字段 nameStudent 类。注意我们已将 Program 类从 Student 类中继承。

// 访问 name 字段并打印
Console.WriteLine("Name: " + program.name);

由于受保护的成员可以在派生类中访问,我们可以从 Program 类中访问 name

4. internal 访问修饰符

当我们声明一个类型或类型成员为 internal 时,它只能在同一个程序集中访问。

程序集是类型(类、接口等)和资源(数据)的集合。它们构建在一起,形成功能的逻辑单元。

这就是为什么当我们运行一个程序集时,程序集内的所有类和接口一起运行。要了解更多,请访问 C# 程序集

示例:同一程序集中的 internal

using System;

namespace Assembly {

class Student {
internal string name = "Sheeran";
}

class Program {
static void Main(string[] args) {

// 创建 Student 类的对象
Student theStudent = new Student();

// 访问 name 字段并打印
Console.WriteLine("Name: " + theStudent.name);
Console.ReadLine();
}
}
}

输出

Name: Sheeran

在上述示例中,我们创建了一个名为 Student 的类,其中有一个字段 name。由于该字段是 internal 的,我们可以从 Program 类访问它,因为它们位于同一个程序集中。

如果在单个程序集中使用 internal,它的作用就像 public 访问修饰符一样。

示例:在不同程序集中使用 internal

首先创建一个程序集。

// Assembly1 中的代码
using System;

namespace Assembly1 {

public class StudentName {
internal string name = "Sheeran";
}

class Program {
static void Main(string[] args) {
}
}
}

这里,代码位于 Assembly1。我们在 StudentName 类内部创建了一个内部字段 name。现在,这个字段只能从同一个程序集 Assembly1 访问。

现在,让我们创建另一个程序集。

// Assembly2 中的代码
using System;

// 访问 Assembly1
using Assembly1;

namespace Assembly2 {
class Program {
static void Main(string[] args) {
StudentName student = new StudentName();

// 访问 Assembly1 中的 name 字段
Console.Write(student.name);
Console.ReadLine();
}
}
}

这里,代码位于 Assembly2。我们试图访问 StudentName 类(Assembly1)的 name 字段。

要从 Assembly1 访问字段,我们首先需要在 Assembly2 中设置 Assembly1 的引用。现在代码

using Assembly1;

允许我们在 Assembly2 中使用 Assembly1 的代码。

在这里,当我们试图从 Assembly2 访问 name 字段时,会出现错误。

**错误**    CS0122    'StudentName.name' 由于其保护级别而无法访问

这是因为 nameAssembly1 中的一个内部字段。

5. protected internal 访问修饰符

protected internalprotectedinternal 访问修饰符的组合。

当我们声明一个成员为 protected internal 时,它可以从同一程序集中访问,也可以从任何其他程序集中包含该类的派生类中访问。

// Assembly1 中的代码
using System;

namespace Assembly1 {
public class Greet {
protected internal string msg="Hello";
}

class Program {
static void Main(string[] args) {
Greet greet = new Greet();
Console.WriteLine(greet.msg);
Console.ReadLine();
}
}
}

输出

Hello

上述代码位于 Assembly1

在上述示例中,我们创建了一个名为 Greet 的类,其中有一个字段 msg。由于该字段是 protected internal 的,我们可以从 Program 类访问它,因为它们位于同一个程序集。

让我们在另一个程序集中从 Greet 派生一个类,并尝试访问它的 protected internal 字段 msg

// Assembly2 中的代码
using System;

// 访问 Assembly1
using Assembly1;

namespace Assembly2 {

// Greet 的派生类
class Program: Greet {
static void Main(string[] args) {
Program greet = new Program();

// 访问 Assembly1 中的 name 字段
Console.Write(greet.msg);
Console.ReadLine();
}
}
}

输出

Hello

上述代码在 Assembly2 中。

在上面的示例中,我们让 Program 类继承自 Assembly1 中的 Greet 类。

// 从 Assembly1 访问 name 字段
Console.Write(greet.msg);

我们能够从 Assembly2 中访问 Assembly1Greet 类中的 msg

这是因为 msg 是一个受保护的内部字段,我们试图从 Greet 的子类中访问它。

6. private protected 访问修饰符

private protected 访问修饰符是 privateprotected 的结合体。它从 C# 版本 7.2 起提供。

当我们声明一个成员为 private protected 时,它只能在同一个类中,以及同一个程序集中的派生类中被访问。例如,

// Assembly1 中的代码
using System;

namespace Assembly1 {
public class StudentName {
private protected string name = "Sheeran";
}

// StudentName 类的派生类
class Program1 : StudentName {

static void Main(string[] args) {

Program1 student = new Program1();

// 从基类访问 name 字段
Console.Write(student.name);
Console.ReadLine();
}
}
}

输出

Sheeran

上述代码在 Assembly1

在上述示例中,我们创建了一个带有 private protected 字段 nameStudentName 类。

注意我们让 Program1 类继承自 StudentName 类。

由于 private protected 成员可以在同一程序集的派生类中访问,我们可以在 Program1 类中访问 name

现在,让我们在另一个程序集中派生一个类自 StudentName,并尝试从中访问 private protected 字段 name。例如,

// Assembly2 中的代码
using System;
// 访问 Assembly1
using Assembly1;

namespace Assembly2 {

// StudentName 的派生类
class Program : StudentName {
static void Main(string[] args) {
Program student = new Program();

// 从 Assembly1 访问 name 字段
Console.Write(student.name);
Console.ReadLine();
}
}
}

上述代码在 Assembly2

在上述示例中,当我们尝试从 StudentName 的派生类中访问 name 字段时,我们会遇到错误。

**错误**    CS0122    'StudentName.name' 由于其保护级别而无法访问

这是因为 name 字段在 Assembly1 中,而派生类在 Assembly2 中。

注意:我们也可以将访问修饰符用于类型(类、接口等)。然而,我们只能将类型与 public 和 internal 访问修饰符一起使用。