前言
本文會先分别解釋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方法,我可以順利的調用它,如下所示:
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方法中我嘗試調用前面一個程式集,結果報錯,因為跨越了程式集,無權通路:
using 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修飾的方法,在同一個程式集(項目)中可以在任意地方都可以使用改方法,如下所示:
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就可以使用了(即使跨程式集):
using 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