C# 15부터 클래스에 closed 한정자를 적용하여 닫힌 계층을 선언할 수 있습니다. 선언 어셈블리 내의 닫힌 클래스에서 직접 하위 형식만 파생할 수 있습니다. 직접 하위 항목 집합이 고정 switch 되어 있으므로 각 직계 하위 항목을 처리하는 식은 닫힌 기본 형식을 소모하며 기본 arm이 필요하지 않습니다.
// Assembly 1
public closed record class JobStatus;
public record class Queued : JobStatus;
public record class Running(int PercentComplete) : JobStatus;
public record class Completed(TimeSpan Elapsed) : JobStatus;
public record class Failed(string Error) : JobStatus;
// Assembly 2
public record class Paused : JobStatus; // Error: 'JobStatus' is a closed class
동일한 어셈블리 제한은 닫힌 클래스의 직접 하위 항목에만 적용됩니다. 닫힌 클래스에서 파생되는 클래스는 사용자가 표시 closed하지 않는 한 자체 닫혀 있지 않습니다.
Failed 이전 예제에서는 일반 레코드이므로 다른 어셈블리가 파생할 수 있습니다.
// Assembly 2
public record class RetryableFailed(string Error, int Attempts) : Failed(Error); // OK: 'Failed' isn't sealed or closed
파생
C# 언어 참조는 가장 최근에 릴리스된 C# 언어 버전을 문서화합니다. 또한 예정된 언어 릴리스의 공개 미리 보기 기능에 대한 초기 설명서도 포함되어 있습니다.
설명서는 언어의 마지막 세 버전 또는 현재 공개 미리 보기에서 처음 도입된 기능을 식별합니다.
Tip
C#에서 기능이 처음 도입된 시기를 찾으려면 C# 언어 버전 기록에 대한 문서를 참조하세요.
메모
closed 는 상황에 맞는 키워드입니다. 클래스 선언에서 한정자로 표시되는 경우에만 특별한 의미가 있습니다. 다른 컨텍스트에서 식별자로 계속 사용할 closed 수 있습니다. 한정자가 유효한 위치에서 식별자로 사용해야 closed 하는 경우 컴파일러에 한정자가 아닌 식별자로 처리하도록 지시하는 접두사(예@closed: )를 접두 @ 사로 지정합니다.
선언 규칙
한 closed 정자는 클래스 한정자입니다.
-
closed클래스는 암시적으로abstract. 또는 명시적abstract한정자와 결합staticclosedsealed할 수 없습니다. - 닫힌 기본 클래스와 동일한 어셈블리 및 모듈에서 닫힌 클래스의 직접 하위 형식을 선언해야 합니다.
- 닫힌 클래스에서 파생되는 클래스 자체는 닫혀 있지 않습니다. 파생 클래스도
closed닫으려면 한정자를 다시 적용합니다.
제네릭 클래스가 클래스에서 closed 직접 파생되는 경우 파생 클래스의 모든 형식 매개 변수를 기본 클래스 사양에서 사용해야 합니다. 이 규칙은 한정자 자체에 관한 closed 것이 아닙니다. 닫힌 생성된 형식은 형식 인수가 완전히 지정된 제네릭 형식입니다(예: Tree<int>열린 형식과는 Tree<T>반대). 규칙은 기본 클래스의 닫힌 생성된 각 형식이 직접 하위 항목 중 정확히 하나의 닫힌 생성 형식을 갖도록 하므로 컴파일러가 완전성을 추론할 수 있습니다.
public closed record class Tree<T>;
public record class Leaf<T>(T Value) : Tree<T>; // OK: 'T' appears in the base class
public record class Branch<T>(Tree<T> Left, Tree<T> Right) : Tree<T>; // OK: 'T' appears in the base class
public record class Constant<U>(U Value) : Tree<int> { } // Error: 'U' isn't used in the base class
완전 스위치 식
식이 switch 닫힌 클래스의 모든 직계 하위 항목을 처리하는 경우 컴파일러는 스위치를 완전하게 간주하고 완전하지 않은 경고를 생성하지 않습니다.
public static string Describe(JobStatus status) => status switch
{
Queued => "waiting to start",
Running(var percent) => $"{percent}% complete",
Completed(var elapsed) => $"finished in {elapsed.TotalSeconds:F1}s",
Failed(var error) => $"failed: {error}",
// No warning: every direct descendant of 'JobStatus' is handled.
};
스위치 제어 식이 nullable null 이면 스위치가 처리해야 하는 또 다른 가능한 값이 됩니다. 스위치는 JobStatus? 다음을 포함하는 경우에만 완전합니다.null
public static string DescribeOrUnknown(JobStatus? status) => status switch
{
null => "unknown",
Queued => "waiting to start",
Running(var percent) => $"{percent}% complete",
Completed(var elapsed) => $"finished in {elapsed.TotalSeconds:F1}s",
Failed(var error) => $"failed: {error}",
// No warning: every direct descendant of 'JobStatus' is handled, and null is handled.
};
암을 null 생략하면 컴파일러는 패턴 null 이 처리되지 않는다고 경고합니다. 닫힌 형식이 클래스인지 아니면 nullable 형식으로 리프트된 구조체인지에 관계없이 동일한 규칙이 적용됩니다.
닫힌 계층이 제네릭 제약 조건 및 접근성과 상호 작용하는 방법을 포함하여 컴파일러가 완전성을 결정하는 방법에 대한 자세한 내용은 닫힌 계층 패턴을 참조하세요.
닫힌 형식으로 제한되는 형식 매개 변수
닫힌 클래스로 제한되는 형식 매개 변수는 완전성 검사를 위해 닫힌 클래스로 처리됩니다.
switch 닫힌 제약 조건의 모든 직접 하위 항목을 처리할 때 해당 형식 매개 변수가 있는 관리 값의 식은 완전합니다.
public static string DescribeJob<X>(X status) where X : JobStatus => status switch
{
Queued => "waiting to start",
Running(var percent) => $"{percent}% complete",
Completed(var elapsed) => $"finished in {elapsed.TotalSeconds:F1}s",
Failed(var error) => $"failed: {error}",
// No warning: 'X' is constrained to a closed type, so its direct descendants exhaust the switch.
};
이 규칙은 형식 매개 변수가 메서드에 표시되는지 또는 포함하는 형식에 표시되는지 여부에 따라 적용됩니다.
C# 언어 사양
자세한 내용은 닫힌 계층 기능 사양을 참조하세요.
참고하십시오
.NET