private protected
private protected (C# Reference)
C#에서 어떤 멤버를 어디까지 공개할지 정하는 '접근 한정자(access modifier)' 가운데 하나예요. private protected 멤버는 그 클래스에서 파생된 타입이면서, 동시에 그 클래스가 들어 있는 어셈블리 안에서 선언된 타입만 접근할 수 있어요. 다른 접근 한정자들과 한눈에 비교하고 싶다면 Accessibility Levels를 보면 돼요.
본문
파생 타입이 기본 클래스의 private protected 멤버에 접근할 수 있는 조건이 하나 더 붙어요. 그 멤버에 접근하는 변수의 정적 타입이 파생 클래스 타입이어야 해요. 즉, 안전하게는 '같은 어셈블리에 있는 파생 클래스'지만, 실제로는 '파생 클래스 인스턴스를 거쳐서'만 접근할 수 있다는 뜻이에요. 코드로 확인해 볼게요:
// Assembly1.cs
// Compile with: /target:library
public class BaseClass
{
private protected int myValue = 0;
}
public class DerivedClass1 : BaseClass
{
void Access()
{
var baseObject = new BaseClass();
// Error CS1540, because myValue can only be accessed by
// classes derived from BaseClass.
// baseObject.myValue = 5;
// OK, accessed through the current derived class instance
myValue = 5;
}
}
// Assembly2.cs
// Compile with: /reference:Assembly1.dll
class DerivedClass2 : BaseClass
{
void Access()
{
// Error CS0122, because myValue can only be
// accessed by types in Assembly1
// myValue = 10;
}
}
이 예시는 Assembly1.cs와 Assembly2.cs 두 파일로 되어 있어요. 첫 번째 파일에는 public 기본 클래스 BaseClass와 그로부터 파생된 DerivedClass1이 들어 있어요. BaseClass는 private protected 멤버 myValue를 갖고 있는데, DerivedClass1은 같은 어셈블리 안에서 상속받은 멤버로 이 값에 접근할 수 있어요.
두 번째 파일에서는 DerivedClass2가 상속받은 멤버로 myValue에 접근하려고 하면 오류가 나요. 이유는 private protected 멤버는 같은 어셈블리 안의 파생 타입만 접근할 수 있기 때문이에요. 여기가 바로 protected(어느 어셈블리의 파생 클래스든 접근 가능)나 protected internal(같은 어셈블리의 모든 클래스, 또는 어느 어셈블리의 파생 클래스까지 접근 가능)과 가장 크게 갈리는 지점이에요.
만약 Assembly1.cs에 Assembly2를 이름으로 지정한 xref:System.Runtime.CompilerServices.InternalsVisibleToAttribute가 있다면, 파생 클래스 DerivedClass2는 BaseClass에 선언된 private protected 멤버에 접근할 수 있게 돼요. InternalsVisibleTo가 private protected 멤버를 다른 어셈블리의 파생 클래스에 보이게 만들어 주는 거죠.
다른 protected 접근 한정자와의 비교
세 가지 protected 접근 한정자의 차이를 표로 정리하면 이렇게 돼요:
| Access Modifier | Same Assembly, Derived Class | Same Assembly, Non-derived Class | Different Assembly, Derived Class |
|---|---|---|---|
protected |
✔️ | ❌ | ✔️ |
protected internal |
✔️ | ✔️ | ✔️ |
private protected |
✔️ | ❌ | ❌ |
protected는 어느 어셈블리의 파생 클래스에서 멤버에 접근하게 하고 싶을 때 써요.protected internal은 가장 관대한 접근을 허용할 때 써요(같은 어셈블리의 어떤 클래스, 또는 어디서든 파생 클래스).private protected는 가장 제한적인 protected 접근을 원할 때 써요(같은 어셈블리 안의 파생 클래스만).
참고로 private protected는 구조체(struct) 멤버에는 선언할 수 없어요. 구조체는 상속이 불가능하거든요.
C# 언어 사양
자세한 사양은 C# 언어 사양 문서를 참고하면 돼요.