C# 存取修飾詞 - internal

-- Pageviews

遇過不少 .NET 工程師,都知道 C# 存取修飾詞有四種,publicprotectedprivateinternal
前三種大部都可以很輕易的回答出來,但知道internal的工程師比例卻不高。
本篇來幫大家複習一下 C# 的存取修飾詞 internal

存取範圍

internal的存取範圍是相同組件(Assembly)都可以使用,白話一點講就是internal可以在同一個dll內存取。

  • 類別預設的存取修飾詞是 internal
  • 類別成員預設的存取修飾詞是 private

protected internal

internal可以跟protected合在一起使用,存取範圍就變成:

相同組件 子類別都可以存取。

如下範例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
namespace AssemblyA
{
class Parent
{
protected internal int Number;
}

class Sample
{
public void Method()
{
var parent = new Parent();
// 因為 Number 帶有 internal,所以沒繼承也能存取
parent.Number = 10;
}
}
}

namespace AssemblyB
{
class Child : AssemblyA.Parent
{
public void Method()
{
// 因為 Number 帶有 protected,所以在不同組建也能存取
Number = 20;
}
}
}

Friend Assembly

為了符合封裝原則,基本上我們不太希望把不該開放的類別或成員給外部的組件存取,但為了測試專案,不開放存取權限又顯得很難做事。
這時候我們可以透過 InternalsVisibleTo 開放特定的組件也能存取internal修飾詞的類別或成員。

例如我們有 AssemblyAAssemblyA.Tests 專案,我們希望 AssemblyA.Tests 專案可以存取 AssemblyA 專案的internal類別或成員。

打開 AssemblyA 專案底下的 Properties\AssemblyInfo.cs 檔案編輯:

C# 存取修飾詞 - internal Friend Assembly

1
2
3
4
5
using System.Runtime.CompilerServices;

//...

[assembly: InternalsVisibleTo("AssemblyA.Tests")]

以上設定並不是把 AssemblyAAssemblyA.Tests 變成同組件,而是:

AssemblyA.Tests 可以存取 AssemblyAinternal類別及成員。
AssemblyA 依然不可以存取 AssemblyA.Testsinternal類別及成員。

參考