前言
本文会先分别解释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中这样的用法就是不对的:
using System;using static System.Console;using System.Threading;namespace ConsoleApp_Test{class Program{static void Main(string[] args){DerivedStudent.DoHomeWork(); // 错误用法,会报错访问级别不够ReadKey();}}public class Student{protected static void DoHomeWork(){WriteLine("Do Work!");}}public class DerivedStudent : Student{public static void SayHi(){WriteLine("hi~");DoHomeWork();}}}
在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 {
static void Main(string[] args){Student.DoHomeWork();ReadKey();}}public class Student{internal static void DoHomeWork(){WriteLine("Do homework!~");}}
}
- 现在我在同一个解决方案(Solution)中又创建了另一个项目(Project),叫做ConsoleApp2_Assembly,在这里面的Program的Main方法中我尝试调用前面一个程序集,结果报错,因为跨越了程序集,无权访问:```csharpusing ConsoleApp_Test;using static System.Console;namespace ConsoleApp2_Assembly{class Program{static void Main(string[] args){Student.DoHomeWork();ReadKey();}}}
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 {
static void Main(string[] args){Student.DoHomeWork(); // 不在继承链上的Program类可以调用ReadKey();}}public class Student{protected internal static void DoHomeWork(){WriteLine("Do homework!~");}}public class DerivedStudent : Student{public static void SayHi(){WriteLine("hi~");DoHomeWork(); // 在继承链里面也可以调用}}
}
- 现在跨程序集了,我尝试在ConsoleApp2_Assembly中的Main方法中直接调用Student里面的DoHomeWork方法却无法做到:- 但当我将Program改为继承链上的类,即继承于Student或者DerivedStudent就可以使用了(即使跨程序集):```csharpusing ConsoleApp_Test;using static System.Console;namespace ConsoleApp2_Assembly{class Program:DerivedStudent{static void Main(string[] args){Student.DoHomeWork();ReadKey();}}}
参考文献
[1] Microsoft Docs: Access Modifiers (C# Programming Guide). https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/access-modifiers
