Microsoft MVP성태의 닷넷 이야기
글쓴 사람
정성태 (techsharer at outlook.com)
홈페이지
첨부 파일

(시리즈 글이 18개 있습니다.)
.NET Framework: 1110. C# 11 - 인터페이스 내에 정적 추상 메서드 정의 가능 (DIM for Static Members)
; https://www.sysnet.pe.kr/2/0/12814

.NET Framework: 1118. C# 11 - 제네릭 타입의 특성 적용
; https://www.sysnet.pe.kr/2/0/12839

.NET Framework: 1182. C# 11  - ref struct에 ref 필드를 허용
; https://www.sysnet.pe.kr/2/0/13015

.NET Framework: 2025. C# 11  - 원시 문자열 리터럴(raw string literals)
; https://www.sysnet.pe.kr/2/0/13085

.NET Framework: 2026. C# 11 - 문자열 보간 개선 2가지
; https://www.sysnet.pe.kr/2/0/13086

.NET Framework: 2030. C# 11 - UTF-8 문자열 리터럴
; https://www.sysnet.pe.kr/2/0/13096

.NET Framework: 2031. C# 11 - 사용자 정의 checked 연산자
; https://www.sysnet.pe.kr/2/0/13099

.NET Framework: 2032. C# 11 - shift 연산자 재정의에 대한 제약 완화 (Relaxing Shift Operator)
; https://www.sysnet.pe.kr/2/0/13100

.NET Framework: 2035. C# 11 - 새로운 연산자 ">>>" (Unsigned Right Shift)
; https://www.sysnet.pe.kr/2/0/13110

.NET Framework: 2036. C# 11 - IntPtr/UIntPtr과 nint/nuint의 통합
; https://www.sysnet.pe.kr/2/0/13111

.NET Framework: 2037. C# 11 - 목록 패턴(List patterns)
; https://www.sysnet.pe.kr/2/0/13112

.NET Framework: 2038. C# 11 - Span 타입에 대한 패턴 매칭 (Pattern matching on ReadOnlySpan<char>)
; https://www.sysnet.pe.kr/2/0/13113

.NET Framework: 2042. C# 11 - 파일 범위 내에서 유효한 타입 정의 (File-local types)
; https://www.sysnet.pe.kr/2/0/13117

.NET Framework: 2045. C# 11 - 메서드 매개 변수에 대한 nameof 지원
; https://www.sysnet.pe.kr/2/0/13122

.NET Framework: 2046. C# 11 - 멤버(속성/필드)에 지정할 수 있는 required 예약어 추가
; https://www.sysnet.pe.kr/2/0/13123

.NET Framework: 2048. C# 11 - 구조체 필드의 자동 초기화(auto-default structs)
; https://www.sysnet.pe.kr/2/0/13125

.NET Framework: 2049. C# 11 - 정적 메서드에 대한 delegate 처리 시 cache 적용
; https://www.sysnet.pe.kr/2/0/13126

.NET Framework: 2102. C# 11 - ref struct/ref field를 위해 새롭게 도입된 scoped 예약어
; https://www.sysnet.pe.kr/2/0/13276




C# 11 - 파일 범위 내에서 유효한 타입 정의 (File-local types)

(이번 기능은 Visual Studio 17.4 preview 1 이후 버전에서 테스트할 수 있습니다.)

C/C++ 언어의 경우, 파일 내에서 정의한 전역 변수를 다른 파일에서 사용하지 못하게 만들려면 static으로 정의할 수 있습니다.

// test.cpp

static int _var;

C#에서는 접근 제한자(access modifier)로 저런 접근성을 제어하게 되는데요, 아쉽게도 현재 제공하고 있는 유형으로는 파일 내에서만 유효한 타입을 정의하는 것이 불가능합니다.

그나마 유사한 것이 "internal" 유형인데, 다른 어셈블리에서만 사용하는 것을 막을 수 있을 뿐 같은 프로젝트 내의 다른 C# 파일에서 사용하는 것을 막진 못합니다. 바로 이런 경우, C# 11부터 "file" 접근자를 클래스에 부여할 수 있습니다.

// Program.cs

using System;

TestLocal tl = new TestLocal(); // 컴파일 오류: "file class"로 정의한 타입은 다른 파일에서 사용할 수 없음

// --------------- [파일 분리] ------------------------

// Test.cs

file class TestLocal
{
}

파일 내에서만 유효하므로, 당연히 다른 파일에서 동일한 이름으로 정의하는 것도 가능합니다.

// Test1.cs

namespace MY; // C# 10 - (13) 단일 파일 내에 적용되는 namespace 선언
file class TestLocal
{
}

// --------------- [파일 분리] ------------------------

// Test2.cs

namespace MY;
file class TestLocal
{
}

뭐랄까, 메서드 내부에서만 사용할 수 있도록 (C# 7.0) 로컬 함수를 추가했던 것처럼, 파일 내부에서만 사용할 수 있는 로컬 클래스를 제공하는 것과 유사한 듯합니다. 단지, 로컬 함수의 경우에는 예약어까지 필요하지는 않았지만 class의 경우에는 처음부터 중첩 클래스를 허용했으므로 부득이 "file" 제한자를 추가해야 했을 것입니다.

이런 특징들로 인해 file class는 (같은 파일 내에 있는) 일반 클래스에서 사용할 때 몇 가지 제약이 있습니다.

class Test
{
    // 컴파일 오류: Error CS9051 File-local type 'TestLocal' cannot be used in a member signature in non-file-local type 'Test'.
    TestLocal _tl; // 멤버 필드로는 사용할 수 없고,

    public Test()
    {
        TestLocal t2 = new TestLocal(); // 메서드 내에서는 사용 가능
    }

    // 컴파일 오류: File-local type 'TestLocal' cannot be used in a member signature in non-file-local type 'Test'.
    public TestLocal Get() => new TestLocal(); // 메서드의 반환 타입으로 사용할 수 없음.                          
}

file class TestLocal { }

이러한 제약은, 아마도 private 이외의 유형인 경우 다른 파일에서 상속받은 클래스에서도 접근하게 되므로 원칙상 맞지 않는다고 본 것 같습니다. 물론 유일하게 private 필드라면 상관없었을 수도 있겠지만... 일관성 차원에서, 혹은 일단 구현이 복잡해지므로 아예 전부 막은 것일지도 모르겠습니다.

그 외의 당연한 제약이라면, "file class"는 오직 또 다른 "file class"에만 상속이 가능하고,

// file class 유형은 반드시 file class 타입에서만 상속 가능
file class LocalFromLocal : TestLocal {
    TestLocal t1; // file class 유형에서는 필드로 정의하는 것도 가능

    public TestLocal Get() => new TestLocal(); // 메서드의 반환 타입으로 사용하는 것도 가능
}

// 그렇지 않은 경우 컴파일 에러 - error CS9053: File-local type 'TestLocal' cannot be used as a base type of non-file-local type 'ClassFromLocal'.
class ClassFromLocal : TestLocal { }

file class TestLocal { }

의미가 상충되는 다른 접근 제한자를 함께 사용할 수는 없습니다.

// private은 애초에 class에는 적용할 수 없으므로
// public 또는 internal을 함께 사용하면 컴파일 오류

public file class LocalType1 { } // error CS9052: File - local type 'LocalType1' cannot use accessibility modifiers.
internal file class LocalType1 { } // error CS9052: File - local type 'LocalType1' cannot use accessibility modifiers.

예상하셨겠지만, 로컬 함수와 마찬가지로 file class 역시 컴파일 시에 다음과 같은 식으로 이름이 변경돼 빌드가 됩니다.

using System;

internal class <Test>F1__TestLocal
{
    public <Test>F1__TestLocal()
    {
    }
}




어쩌면 "file" 대신 기존의 private 접근 제한자를 활용했으면 어땠을까 싶습니다. 어차피 기존에도 class에 대해 "private"을 사용할 수 없었기 때문에,

// 컴파일 에러 - error CS1527: Elements defined in a namespace cannot be explicitly declared as private, protected, protected internal, or private protected
private class TestPrivate
{
}

하위 호환성에 대한 염려도 없고 의미상으로도 괜찮을 듯한데요, ^^ 그런데, 이에 대해 문서를 보면,

Drawbacks

It may be inconvenient to be unable to declare file-scoped methods, properties, etc., even those with private or internal accessibility. The feature may not be viable for some use cases if it can only be adopted at the type level.


메서드나 프로퍼티 등에는 사용할 수 없다는 불편함을 언급하고 있으므로, 만약 저런 멤버에도 적용할 계획이라면 private이 아닌 file로 새롭게 추가한 것이 맞겠습니다. ^^




C# 11 - 인터페이스 내에 정적 추상 메서드 정의 가능 (공식 문서, Static Abstract Members In Interfaces C# 10 Preview)
; https://www.sysnet.pe.kr/2/0/12814

C# 11 - 제네릭 타입의 특성 적용 (공식 문서, Generic attributes)
; https://www.sysnet.pe.kr/2/0/12839

C# 11 - 사용자 정의 checked 연산자 (공식 문서, Checked user-defined operators)
; https://www.sysnet.pe.kr/2/0/13099

C# 11 - shift 연산자 재정의에 대한 제약 완화 (공식 문서, Relaxing Shift Operator)
; https://www.sysnet.pe.kr/2/0/13100

C# 11 - IntPtr/UIntPtr과 nint/unint의 통합 (공식 문서, Numeric IntPtr)
; https://www.sysnet.pe.kr/2/0/13111

C# 11 - 새로운 연산자 ">>>" (Unsigned Right Shift) (공식 문서, Unsigned right shift operator)
; https://www.sysnet.pe.kr/2/0/13110

C# 11 - 원시 문자열 리터럴 (공식 문서, raw string literals)
; https://www.sysnet.pe.kr/2/0/13085

C# 11 - 문자열 보간 개선 2가지 (공식 문서, Allow new-lines in all interpolations)
; https://www.sysnet.pe.kr/2/0/13086

C# 11 - 목록 패턴 (공식 문서, List patterns)
; https://www.sysnet.pe.kr/2/0/13112

C# 11 - Span 타입에 대한 패턴 매칭 (공식 문서, Pattern matching on ReadOnlySpan<char>)
; https://www.sysnet.pe.kr/2/0/13113

C# 11 - Utf8 문자열 리터럴 지원 (공식 문서, Utf8 Strings Literals)
; https://www.sysnet.pe.kr/2/0/13096

C# 11 - ref struct에 ref 필드를 허용 (공식 문서, ref fields)
; https://www.sysnet.pe.kr/2/0/13015

C# 11 - 파일 범위 내에서 유효한 타입 정의 (공식 문서, File-local types)
; https://www.sysnet.pe.kr/2/0/13117

C# 11 - 메서드 매개 변수에 대한 nameof 지원 (공식 문서, nameof(parameter))
; https://www.sysnet.pe.kr/2/0/13122

C# 11 - 멤버(속성/필드)에 지정할 수 있는 required 예약어 추가 (공식 문서, Required members)
; https://www.sysnet.pe.kr/2/0/13123

C# 11 - 구조체 필드의 자동 초기화 (공식 문서, auto-default structs)
; https://www.sysnet.pe.kr/2/0/13125

C# 11 - 정적 메서드에 대한 delegate 처리 시 cache 적용 (공식 문서, Cache delegates for static method group)
; https://www.sysnet.pe.kr/2/0/13126

Language Feature Status
; https://github.com/dotnet/roslyn/blob/main/docs/Language%20Feature%20Status.md




[이 글에 대해서 여러분들과 의견을 공유하고 싶습니다. 틀리거나 미흡한 부분 또는 의문 사항이 있으시면 언제든 댓글 남겨주십시오.]







[최초 등록일: ]
[최종 수정일: 5/5/2023]

Creative Commons License
이 저작물은 크리에이티브 커먼즈 코리아 저작자표시-비영리-변경금지 2.0 대한민국 라이센스에 따라 이용하실 수 있습니다.
by SeongTae Jeong, mailto:techsharer at outlook.com

비밀번호

댓글 작성자
 




... 16  17  18  19  20  21  [22]  23  24  25  26  27  28  29  30  ...
NoWriterDateCnt.TitleFile(s)
13082정성태6/19/20226320.NET Framework: 2023. C# - Process의 I/O 사용량을 보여주는 GetProcessIoCounters Win32 API파일 다운로드1
13081정성태6/17/20226395.NET Framework: 2022. C# - .NET 7 Preview 5 신규 기능 - System.IO.Stream ReadExactly / ReadAtLeast파일 다운로드1
13080정성태6/17/20227008개발 환경 구성: 643. Visual Studio 2022 17.2 버전에서 C# 11 또는 .NET 7.0 preview 적용
13079정성태6/17/20224657오류 유형: 814. 파이썬 - Error: The file/path provided (...) does not appear to exist
13078정성태6/16/20226713.NET Framework: 2021. WPF - UI Thread와 Render Thread파일 다운로드1
13077정성태6/15/20227071스크립트: 40. 파이썬 - PostgreSQL 환경 구성
13075정성태6/15/20226034Linux: 50. Linux - apt와 apt-get의 차이 [2]
13074정성태6/13/20226316.NET Framework: 2020. C# - NTFS 파일에 사용자 정의 속성값 추가하는 방법파일 다운로드1
13073정성태6/12/20226551Windows: 207. Windows Server 2022에 도입된 WSL 2
13072정성태6/10/20226833Linux: 49. Linux - ls 명령어로 출력되는 디렉터리 색상 변경 방법
13071정성태6/9/20227414스크립트: 39. Python에서 cx_Oracle 환경 구성
13070정성태6/8/20227221오류 유형: 813. Windows 11에서 입력 포커스가 바뀌는 문제 [1]
13069정성태5/26/20229447.NET Framework: 2019. C# - .NET에서 제공하는 3가지 Timer 비교 [2]
13068정성태5/24/20227975.NET Framework: 2018. C# - 일정 크기를 할당하는 동안 GC를 (가능한) 멈추는 방법 [1]파일 다운로드1
13067정성태5/23/20227285Windows: 206. Outlook - 1년 이상 지난 메일이 기본적으로 안 보이는 문제
13066정성태5/23/20226645Windows: 205. Windows 11 - Windows + S(또는 Q)로 뜨는 작업 표시줄의 검색 바가 동작하지 않는 경우
13065정성태5/20/20227297.NET Framework: 2017. C# - Windows I/O Ring 소개 [2]파일 다운로드1
13064정성태5/18/20226900.NET Framework: 2016. C# - JIT 컴파일러의 인라인 메서드 처리 유무
13063정성태5/18/20227323.NET Framework: 2015. C# - 인라인 메서드(inline methods)
13062정성태5/17/20228053.NET Framework: 2014. C# - async/await 그리고 스레드 (4) 비동기 I/O 재현파일 다운로드1
13061정성태5/16/20226877.NET Framework: 2013. C# - FILE_FLAG_OVERLAPPED가 적용된 파일의 읽기/쓰기 시 Position 관리파일 다운로드1
13060정성태5/15/20229370.NET Framework: 2012. C# - async/await 그리고 스레드 (3) Task.Delay 재현파일 다운로드1
13059정성태5/14/20227799.NET Framework: 2011. C# - CLR ThreadPool의 I/O 스레드에 작업을 맡기는 방법 [1]파일 다운로드1
13058정성태5/13/20227695.NET Framework: 2010. C# - ThreadPool.SetMaxThreads 사용법
13057정성태5/12/20229375오류 유형: 812. 파이썬 - ImportError: cannot import name ...
13056정성태5/12/20226509.NET Framework: 2009. C# - async/await 그리고 스레드 (2) MyTask의 호출 흐름 [2]파일 다운로드1
... 16  17  18  19  20  21  [22]  23  24  25  26  27  28  29  30  ...