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

비밀번호

댓글 작성자
 




... 151  152  153  [154]  155  156  157  158  159  160  161  162  163  164  165  ...
NoWriterDateCnt.TitleFile(s)
1202정성태12/21/201126017오류 유형: 144. The database '...' cannot be opened because it is version 661.
1201정성태12/14/201141104디버깅 기술: 47. .NET Reflector를 이용한 "소스 코드가 없는" 어셈블리 디버깅 [4]
1200정성태12/11/201126949디버깅 기술: 46. Windbg 확장 DLL 만들기 (2) - Debugger Extension API 사용파일 다운로드1
1199정성태12/11/201128368VC++: 55. JNI DLL 컴파일 시 x86과 x64의 Export된 함수의 이름이 왜 다를까요? [2]파일 다운로드1
1198정성태12/9/201132172디버깅 기술: 45. Windbg 확장 DLL 만들기 (1) - 스레드를 강제 종료시키는 명령어 [2]파일 다운로드1
1197정성태12/9/201129944.NET Framework: 282. Shader 강좌와 함께 배워보는 XNA Framework (2) - RenderMonkey의 Shader/Model 파일 연동파일 다운로드2
1196정성태12/9/201133136.NET Framework: 281. Shader 강좌와 함께 배워보는 XNA Framework (1) - 기초 프로그램 구조 [3]파일 다운로드2
1195정성태12/8/201147795오류 유형: 143. DXSDK_Jun10.exe 설치 시 "Error Code: S1023" 오류 해결하는 방법 [4]
1194정성태12/8/201135545개발 환경 구성: 137. Visual C++ 런타임 구성요소에 대한 디버그 버전 설치하는 방법
1193정성태12/8/201122585오류 유형: 142. Windows Phone SDK 7.1 설치 시 Expression Blend 제거를 요구하는 경우
1192정성태12/8/201125608개발 환경 구성: 136. Windows 7 SP1의 IIS에서 사용자 프로파일을 로드하는 방법
1191정성태12/6/201126743.NET Framework: 280. MVC3에서 JavaScriptSerializer 재정의하는 방법파일 다운로드1
1190정성태12/6/201129893오류 유형: 141. Visual C++ 컴파일 오류 - error C2275: 'xxxxx' : illegal use of this type as an expression [1]
1189정성태12/6/201137034VS.NET IDE: 70. Visual Studio에서 프로젝트 로드가 안된다면?
1188정성태12/3/201126126개발 환경 구성: 135. 마이크로소프트 TFS 호스팅 서비스 - Preview [3]
1187정성태12/2/201130793개발 환경 구성: 134. Robocopy 오류 및 종료 코드
1186정성태12/1/201132615.NET Framework: 279. WPF - 그리기 성능 및 Blurring 문제파일 다운로드1
1185정성태11/29/201123399.NET Framework: 278. WPF - Content의 Changed 이벤트에 해당하는게 뭔가요?파일 다운로드1
1184정성태11/29/201126199.NET Framework: 277. F#과 WPF가 어울리지 못하는 근본적인 이유 [2]
1183정성태11/26/201121650오류 유형: 140. Visual Studio 2010 - Floating된 에디트 윈도우가 사라지지 않는 경우 [2]
1182정성태11/25/201157412.NET Framework: 276. 중복 없는 숫자를 랜덤으로 배열하는 방법 [5]파일 다운로드1
1181정성태11/24/201127877디버깅 기술: 44. windbg의 mscordacwks DLL 로드 문제
1180정성태11/23/201137687.NET Framework: 275. 레지스트리 등록 및 Interop DLL 없이 COM 개체 사용하는 방법 [2]파일 다운로드1
1179정성태11/22/201128280.NET Framework: 274. ReaderWriterLockSlim은 언제 쓰는 걸까요? [4]파일 다운로드1
1178정성태11/19/201124758.NET Framework: 273. 설치된 .NET 버전에 민감한 코드를 포함하는 경우, 다중으로 어셈블리를 만들어야 할까요?파일 다운로드1
1177정성태11/18/201130005.NET Framework: 272. 소켓 연결 시간 제한 - 두 번째 이야기 [1]파일 다운로드1
... 151  152  153  [154]  155  156  157  158  159  160  161  162  163  164  165  ...