C# 访问修饰符

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

class Student {

  public string name;
    
  private int num;

  }

这里,

  • name - public 字段,可以从任何地方访问
  • num - private 字段,只能在 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) {
    
      // creating object of Student class
      Student student1 = new Student();
      
      // accessing name field and printing it
      Console.WriteLine("Name: " + student1.name);

      // accessing print method from Student
      student1.print();
      Console.ReadLine();
    }
  }
}

输出

Name: Sheeran
Hello from Student class

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

// accessing name field and printing it
Console.WriteLine("Name: " + student1.name);

// accessing print method from Student
student1.print();

由于字段和方法都是 public 的,我们可以在 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) {
    
      // creating object of Student class
      Student student1 = new Student();
      
      // accessing name field and printing it
      Console.WriteLine("Name: " + student1.name);

      // accessing print method from Student
      student1.print();

      Console.ReadLine();
    }
  }
}

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

// accessing name field and printing it
Console.WriteLine("Name: " + student1.name);

// accessing print method from Student
student1.print();

由于字段和方法都是 private 的,我们无法在 Program 类中访问它们。此处,代码将生成以下错误。

Error    CS0122    'Student.name' is inaccessible due to its protection level    
Error    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 {
    static void Main(string[] args) {
    
      // creating object of student class
      Student student1 = new Student();
      
      // accessing name field and printing it
      Console.WriteLine("Name: " + student1.name);
      Console.ReadLine();
    }
  }
}

在上面的示例中,我们创建了一个名为 Student 的类,其中包含一个字段 name。由于该字段是 protected 的,我们无法在 Program 类中访问它。

此处,代码将生成以下错误。

Error    CS0122    'Student.name' is inaccessible due to its protection level    

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

using System;

namespace MyApplication {

  class Student {
    protected string name = "Sheeran";
  }
  
  // derived class
  class Program : Student {
    static void Main(string[] args) {

      // creating object of derived class
      Program program = new Program();
      
      // accessing name field and printing it
      Console.WriteLine("Name: " + program.name);
      Console.ReadLine();
    }
  }
}

输出

Name: Sheeran

在上面的示例中,我们创建了一个名为 Student 的类,其中包含一个 protected 字段 name。请注意,我们已将 Program 类继承自 Student 类。

// accessing name field and printing it
Console.WriteLine("Name: " + program.name);

由于 protected 成员可以从派生类访问,因此我们可以从 Program 类访问 name


4. internal 访问修饰符

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

程序集是类型(类、接口等)和资源(数据)的集合。它们被构建为协同工作并形成功能的逻辑单元。

因此,当我们运行一个程序集时,程序集内的所有类和接口都会一起运行。要了解更多信息,请访问C# 程序集


示例:同一个程序集内的 internal

using System;

namespace Assembly {

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

  class Program {
    static void Main(string[] args) {
    
      // creating object of Student class
      Student theStudent = new Student();
      
      // accessing name field and printing it
      Console.WriteLine("Name: " + theStudent.name);
      Console.ReadLine();
    }
  }
}

输出

Name: Sheeran

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

如果我们使用单个程序集中的 internal,它的作用与 public 访问修饰符相同。


示例:不同程序集中的 internal

我们先创建一个程序集。

// Code on Assembly1
using System;

namespace Assembly1 {

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

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

这里,这段代码在程序集1中。我们在 StudentName 类中创建了一个 internal 字段 name。现在,此字段只能从同一个程序集程序集1访问。

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

// Code on Assembly2
using System;

// access Assembly1
using Assembly1;

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

      // accessing name field from Assembly1
      Console.Write(student.name);
      Console.ReadLine();
     }
  }
}

这里,这段代码在程序集2中。我们正在尝试访问 StudentName 类(程序集1)的 name 字段。

要访问程序集1中的字段,我们首先需要将程序集1的引用设置为程序集2。现在代码

using Assembly1;

允许我们将程序集1中的代码用于程序集2

这里,当我们尝试从程序集2访问 name 字段时,我们会收到一个错误。

Error    CS0122    'StudentName.name' is inaccessible due to its protection level

这是因为 name 是一个 internal 字段,存在于程序集1中。


5. protected internal 访问修饰符

protected internalprotectedinternal 访问修饰符的组合。

当我们声明一个成员为 protected internal 时,它可以在同一程序集和包含类的派生类(来自任何其他程序集)中访问。

// Code on 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

上面的代码在程序集1中。

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

让我们从另一个程序集派生一个类,继承自 Greet,然后尝试从它访问 protected internal 字段 msg

// Code on Assembly2
using System;

// access Assembly1
using Assembly1;

namespace Assembly2 {

  // derived class of Greet
  class Program: Greet {
    static void Main(string[] args) {
      Program greet = new Program();

      // accessing name field from Assembly1
      Console.Write(greet.msg);
      Console.ReadLine();
    }
  }
}

输出

Hello

上面的代码在程序集2中。

在上面的示例中,我们继承了程序集1中的 Greet 类的 Program 类。

// accessing name field from Assembly1
Console.Write(greet.msg);

我们可以从程序集2访问程序集1Greet 类的 msg 字段。

这是因为 msg 是一个 protected internal 字段,并且我们尝试从 Greet 的子类中访问它。


6. private protected 访问修饰符

private protected 访问修饰符是 privateprotected 的组合。它从 C# 7.2 及更高版本可用。

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

// Code in Assembly1
using System;

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

  //derived class of StudentName class
  class Program1 : StudentName {

    static void Main(string[] args) {

      Program1 student = new Program1();

      //  accessing name field from base class
      Console.Write(student.name);
      Console.ReadLine();
    }
  }
}

输出

Sheeran

上面的代码在程序集1

在上面的示例中,我们创建了一个名为 StudentName 的类,其中包含一个 private protected 字段 name

请注意,我们已将 Program1 类继承自 StudentName 类。

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

让我们从另一个程序集派生一个类,继承自 StudentName,然后尝试从它访问 private protected 字段 name。例如,

// Code in Assembly2
using System;
//access Assembly1
using Assembly1;

namespace Assembly2 {

  //derived class of StudentName
  class Program : StudentName {
    static void Main(string[] args) {
      Program student = new Program();
    
      // accessing name field from Assembly1
      Console.Write(student.name);
      Console.ReadLine();
     }
  }
}

上面的代码在程序集2

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

Error    CS0122    'StudentName.name' is inaccessible due to its protection level    

这是因为 name 字段在程序集1中,而派生类在程序集2中。

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

你觉得这篇文章有帮助吗?

我们的高级学习平台,凭借十多年的经验和数千条反馈创建。

以前所未有的方式学习和提高您的编程技能。

试用 Programiz PRO
  • 交互式课程
  • 证书
  • AI 帮助
  • 2000+ 挑战