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)
13056정성태5/12/20226509.NET Framework: 2009. C# - async/await 그리고 스레드 (2) MyTask의 호출 흐름 [2]파일 다운로드1
13055정성태5/11/20229457.NET Framework: 2008. C# - async/await 그리고 스레드 (1) MyTask로 재현 [11]파일 다운로드1
13054정성태5/11/20226902.NET Framework: 2007. C# - 10진수 숫자를 담은 문자열을 숫자로 변환하는 방법 [11]파일 다운로드1
13053정성태5/10/20226557.NET Framework: 2006. C# - GC.KeepAlive 메서드의 역할
13052정성태5/9/20226568.NET Framework: 2005. C# - 생성한 참조 개체가 언제 GC의 정리 대상이 될까요?
13051정성태5/8/20226539.NET Framework: 2004. C# XingAPI - ACF 검색 결과로 구한 CSV 파일을 통해 퀀트 종목 찾기파일 다운로드1
13050정성태5/6/20226572.NET Framework: 2003. C# - COM 개체의 이벤트 핸들러에서 발생하는 예외에 대한 CLR의 특별 대우파일 다운로드1
13049정성태5/6/20225560오류 유형: 811. GoLand - Error: Cannot find package
13048정성태5/6/20226690오류 유형: 810. "ASUS TUF GAMING B550M-PLUS (WI-FI)" 모델에서 블루투스 장치가 인식이 안 되는 문제
13047정성태5/6/20226681오류 유형: 809. Speech Recognition could not start
13046정성태5/5/20226976.NET Framework: 2002. C# XingAPI - ACF 파일을 이용한 퀀트 종목 찾기(t1857)
13045정성태5/5/20226995.NET Framework: 2001. C# XingAPI - 주식 종목에 따른 PBR, PER, ROE 구하는 방법(t3341 예제)
13044정성태5/4/20226446오류 유형: 808. error : clang++ exited with code 127
13043정성태5/3/20226103오류 유형: 807. C# - 닷넷 응용 프로그램에서 Informix DB 사용 시 오류 메시지 정리
13042정성태5/3/20226471.NET Framework: 2000. C# - 닷넷 응용 프로그램에서 Informix DB 사용 방법파일 다운로드1
13041정성태4/28/20226750개발 환경 구성: 642. Informix 데이터베이스 docker 환경 구성
13040정성태4/27/20227258VC++: 156. 비주얼 스튜디오 - Linux C/C++ 프로젝트에서 openssl 링크하는 방법
13039정성태4/27/20228088.NET Framework: 1999. C# - Playwright를 이용한 간단한 브라우저 제어 실습
13038정성태4/26/20225952오류 유형: 806. twine 실행 시 ConfigParser.ParsingError: File contains parsing errors: /root/.pypirc
13037정성태4/25/20226259.NET Framework: 1998. Azure Functions를 사용한 간단한 실습
13036정성태4/24/20227029.NET Framework: 1997. C# - nano 시간을 가져오는 방법 [2]
13035정성태4/22/20227611Windows: 204. Windows 10부터 바뀐 QueryPerformanceFrequency, QueryPerformanceCounter
13034정성태4/21/20226952.NET Framework: 1996. C# XingAPI - 주식 종목에 따른 PBR, PER, ROE, ROA 구하는 방법(t3320, t8430 예제)파일 다운로드1
13033정성태4/18/20227585.NET Framework: 1195. C# - Thread.Yield와 Thread.Sleep(0)의 차이점(?)
13032정성태4/17/20227303오류 유형: 805. Github의 50MB 파일 크기 제한 - warning: GH001: Large files detected. You may want to try Git Large File Storage
13031정성태4/15/20226825.NET Framework: 1194. C# - IdealProcessor와 ProcessorAffinity의 차이점
... 16  17  18  19  20  21  22  [23]  24  25  26  27  28  29  30  ...