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)
1177정성태11/18/201130005.NET Framework: 272. 소켓 연결 시간 제한 - 두 번째 이야기 [1]파일 다운로드1
1176정성태11/17/201129277.NET Framework: 271. C#에서 확인해 보는 관리 힙의 인스턴스 구조 [3]파일 다운로드1
1175정성태11/16/201127242.NET Framework: 270. .NET 참조 개체 인스턴스의 Object Header를 확인하는 방법 [1]파일 다운로드1
1174정성태11/15/201126631.NET Framework: 269. 일반 참조형의 기본 메모리 소비는 얼마나 될까요? [4]
1173정성태11/14/201122815.NET Framework: 268. .NET Array는 왜 12bytes의 기본 메모리를 점유할까? [1]
1172정성태11/13/201119832.NET Framework: 267. windbg - GC Heap에서 .NET 타입에 대한 배열을 찾는 방법
1171정성태11/12/201136509.NET Framework: 266. StringBuilder에서의 OutOfMemoryException 오류 원인 분석 [4]파일 다운로드1
1170정성태11/10/201125742.NET Framework: 265. Named 동기화 개체 생성 시 System.UnauthorizedAccessException 예외 발생하는 경우
1169정성태11/10/201129505.NET Framework: 264. 다중 LAN 카드 환경에서 Dns.GetHostAddresses(local)가 반환해 주는 IP의 우선순위는 어떻게 될까요? [4]
1168정성태11/6/201125352오류 유형: 139. TlbImp : error TI0000 : A single valid machine type compatible with the input type library must be specified
1167정성태11/5/201137149개발 환경 구성: 133. Registry 등록 과정 없이 COM 개체 사용 - 두 번째 이야기 [5]파일 다운로드4
1166정성태11/5/201123242.NET Framework: 263. byte[] pData = new byte[100000]로 인한 성능 차이? [1]파일 다운로드1
1165정성태11/3/201128118개발 환경 구성: 132. "Visual Studio Command Prompt (2010)" 명령행에서 2.0 버전의 MSBuild를 구동하는 방법 [2]파일 다운로드1
1164정성태11/1/201126330.NET Framework: 262. .NET 스레드 콜 스택 덤프 (4) - .NET 4.0을 지원하지 않는 MSE 응용 프로그램 원인 분석
1163정성태10/31/201125833.NET Framework: 261. .NET 스레드 콜 스택 덤프 (3) - MSE 소스 코드 개선파일 다운로드1
1162정성태10/30/201125914.NET Framework: 260. .NET 스레드 콜 스택 덤프 (2) - Managed Stack Explorer 소스 코드를 이용한 스택 덤프 구하는 방법파일 다운로드1
1161정성태10/29/201122774.NET Framework: 259. Type.GetMethod - System.Reflection.AmbiguousMatchException파일 다운로드1
1159정성태10/28/201126206.NET Framework: 258. Roslyn 맛보기 - SyntaxTree 조작 [2]
1158정성태10/24/201125526.NET Framework: 257. Roslyn 맛보기 - Roslyn Symbol / Binding API파일 다운로드1
1157정성태10/23/201129923.NET Framework: 256. Roslyn 맛보기 - Syntax Analysis (Roslyn Syntax API) [2]
1156정성태10/23/201128455.NET Framework: 255. Roslyn 맛보기 - Roslyn Services APIs를 이용한 Code Issue 및 Code Action 기능 소개 [1]
1155정성태10/22/201126487.NET Framework: 254. Roslyn 맛보기 - C# Interactive (2)
1154정성태10/22/201133229.NET Framework: 253. Roslyn 맛보기 - C# Interactive (1)
1153정성태10/21/201142106.NET Framework: 252. Roslyn 맛보기 - C# 소스 코드를 스크립트처럼 다루는 방법 [7]파일 다운로드1
1152정성태10/20/201123757.NET Framework: 251. string.GetHashCode는 hash 값을 cache 할까?
1151정성태10/18/201122682Java: 13. 자바도 64비트에서 (2GB) OutOfMemoryException 예외가 발생할까?
... 151  152  153  154  [155]  156  157  158  159  160  161  162  163  164  165  ...