前言

本文会先分别解释protected和internal的作用,在解释protected internal联合修饰符的作用,因为它们联合在一起是或的含义。

protected

英文解释:The type or member can be accessed only by code in the same class, or in a class that is derived from that class.
说明:在继承链上的类里面都可以使用,但出了类,比如说下面Main中这样的用法就是不对的:

  1. using System;
  2. using static System.Console;
  3. using System.Threading;
  4. namespace ConsoleApp_Test
  5. {
  6. class Program
  7. {
  8. static void Main(string[] args)
  9. {
  10. DerivedStudent.DoHomeWork(); // 错误用法,会报错访问级别不够
  11. ReadKey();
  12. }
  13. }
  14. public class Student
  15. {
  16. protected static void DoHomeWork()
  17. {
  18. WriteLine("Do Work!");
  19. }
  20. }
  21. public class DerivedStudent : Student
  22. {
  23. public static void SayHi()
  24. {
  25. WriteLine("hi~");
  26. DoHomeWork();
  27. }
  28. }
  29. }

在Main方法中调用DerivedStudent.DoHomeWork();是不正确的,因为class Program不在继承链的类内。相反,在DerivedStudent中就可以使用DoHomeWork()方法,当然在Student中也是可以使用的,可以Copy我的代码自己尝试一下。

internal

英文解释:The type or member can be accessed by any code in the same assembly, but not from another assembly.
说明:在相同程序集中可以使用,换句话说就是在同一个项目中的任何代码中都可以调用,包括继承链上的类,不在继承链上的类,但出了项目就没办法使用了。
举个栗子:

  • 现在在ConsoleApp_Test这个项目中,我定义了Student类,里面有一个internal的DoHomework方法,我可以顺利的调用它,如下所示: ```csharp using static System.Console;

namespace ConsoleApp_Test { class Program {

  1. static void Main(string[] args)
  2. {
  3. Student.DoHomeWork();
  4. ReadKey();
  5. }
  6. }
  7. public class Student
  8. {
  9. internal static void DoHomeWork()
  10. {
  11. WriteLine("Do homework!~");
  12. }
  13. }

}

  1. - 现在我在同一个解决方案(Solution)中又创建了另一个项目(Project),叫做ConsoleApp2_Assembly,在这里面的ProgramMain方法中我尝试调用前面一个程序集,结果报错,因为跨越了程序集,无权访问:
  2. ![image.png](https://cdn.nlark.com/yuque/0/2020/png/739899/1597923482271-88640b57-a329-47e9-a2d4-e486a8aa12bc.png#align=left&display=inline&height=364&margin=%5Bobject%20Object%5D&name=image.png&originHeight=364&originWidth=765&size=26003&status=done&style=none&width=765)
  3. ```csharp
  4. using ConsoleApp_Test;
  5. using static System.Console;
  6. namespace ConsoleApp2_Assembly
  7. {
  8. class Program
  9. {
  10. static void Main(string[] args)
  11. {
  12. Student.DoHomeWork();
  13. ReadKey();
  14. }
  15. }
  16. }

protected internal

英文解释:The type or member can be accessed by any code in the assembly in which it’s declared, or from within a derived class in another assembly.
说明:这两个关键字的功能组合是或的关联,也就说被protected internal修饰的成员既可以在继承链上的类里面被访问,也可以在同一个项目中使用。那protected internal与internal有什么区别呢?区别就在于被protected internal修饰的成员可以跨程序集(或者说跨项目)被调用,只要在另一个项目中声明一个属于继承链上的类就可以调用被protected internal修饰的成员(但是在另一个项目的别的地方不能调用)。
举个栗子:

  • 我现在在ConsoleApp_Test中声明了Student和DerivedStudent两个类,Student类中有一个被protected internal修饰的方法,在同一个程序集(项目)中可以在任意地方都可以使用改方法,如下所示: ```csharp using static System.Console;

namespace ConsoleApp_Test { class Program {

  1. static void Main(string[] args)
  2. {
  3. Student.DoHomeWork(); // 不在继承链上的Program类可以调用
  4. ReadKey();
  5. }
  6. }
  7. public class Student
  8. {
  9. protected internal static void DoHomeWork()
  10. {
  11. WriteLine("Do homework!~");
  12. }
  13. }
  14. public class DerivedStudent : Student
  15. {
  16. public static void SayHi()
  17. {
  18. WriteLine("hi~");
  19. DoHomeWork(); // 在继承链里面也可以调用
  20. }
  21. }

}

  1. - 现在跨程序集了,我尝试在ConsoleApp2_Assembly中的Main方法中直接调用Student里面的DoHomeWork方法却无法做到:
  2. ![image.png](https://cdn.nlark.com/yuque/0/2020/png/739899/1597924173753-3eae3867-7050-45ae-a7e3-38a20bf2c8fb.png#align=left&display=inline&height=364&margin=%5Bobject%20Object%5D&name=image.png&originHeight=364&originWidth=676&size=25386&status=done&style=none&width=676)
  3. - 但当我将Program改为继承链上的类,即继承于Student或者DerivedStudent就可以使用了(即使跨程序集):
  4. ![image.png](https://cdn.nlark.com/yuque/0/2020/png/739899/1597924278256-dfbbb61f-22b2-41e4-bccf-68d6a6476889.png#align=left&display=inline&height=350&margin=%5Bobject%20Object%5D&name=image.png&originHeight=350&originWidth=847&size=28221&status=done&style=none&width=847)
  5. ```csharp
  6. using ConsoleApp_Test;
  7. using static System.Console;
  8. namespace ConsoleApp2_Assembly
  9. {
  10. class Program:DerivedStudent
  11. {
  12. static void Main(string[] args)
  13. {
  14. Student.DoHomeWork();
  15. ReadKey();
  16. }
  17. }
  18. }

参考文献

[1] Microsoft Docs: Access Modifiers (C# Programming Guide). https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/access-modifiers