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 - shift 연산자 재정의에 대한 제약 완화 (Relaxing Shift Operator)

(Visual Studio 2022 17.3 이후 버전에서 테스트할 수 있습니다.)

어제의 글을 쓰고 나서,

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

@ekfvoddl3535 님이 다음과 같은 덧글을 남기셨는데요,

재정의 가능한 연산자가 추가된것은 엄청 반갑네요
얼른 c++ 처럼 <<이나 >> 연산자의 2번째 인수타입이 int가 아니더라도 재정의 가능하게 바뀌었으면 하네요 호호..


그에 대해 제가 아는 체 좀 한다고 다음과 같은 덧글을 남겼습니다. ^^

정확한 속내는 잘 모르겠지만, 연산자 재정의에 관한 부정적인 의견도 있기 때문에 아마도 C#의 경우에는 그것을 산술 연산에만 적용하도록 권장하는 듯합니다. 따라서, >>, << 연산자의 경우에도 numeric 관련 타입에 한해 의미가 왜곡되지 않도록 shift 연산이라는 걸로 한정 짓기 때문에 비트 이동을 디지털적인 int 정수 외에는 허용하지 않는 듯하고.

그런 탓에 C++처럼 cout, cin에서 쓰이는 식의 기대는 안 하는 것이 속 편할 것입니다. ^^


그런데, 남기고 나서 왠지 ^^ 찝찝한 느낌이 들어서 검색해 봤더니... ^^; 창피하게도 C# vNext에 그 요구 사항이 있었고,

[Proposal]: Relaxing shift operator requirements #4666
; https://github.com/dotnet/csharplang/issues/4666

이미 Visual Studio 2022 17.3 preview 3에 병합이 되었습니다. 즉, 아마도 C# 11에 포함될 예정입니다. ^^ 어쩔 수 없군요, 기왕 이야기가 나온 김에 이번에는 바로 "Relaxing Shift Operator"를 설명해 보겠습니다.




그런데 막상 설명하려고 보니, 위의 도입부에서 쓴 것이 전부입니다. ^^; 그래서 현재 아래와 같은 식의 코드가 컴파일 됩니다.

C c = new C();
C d = c << 5.8f;

class C
{
    public static C operator << (C c, float o)
    {
        Console.WriteLine("shift operator called with " + o);

        return c;
    }
}

C#의 spec 문서에 따르면,

11.10 Shift operators
; https://github.com/dotnet/csharpstandard/blob/draft-v6/standard/expressions.md#1110-shift-operators

아래와 같은 규칙이 있습니다.

When declaring an overloaded shift operator, the type of the first operand shall always be the class or struct containing the operator declaration, and the type of the second operand shall always be int.


위의 규칙을 소스코드로 설명해 보면, shift 재정의 메서드에서 첫 번째 매개 변수는 반드시 해당 메서드를 포함한 타입이어야 하고, 두 번째 매개 변수는 int 형이어야 한다는 것입니다.

그리고 이번 C# 11에서 풀린 제약은 (첫 번째 매개 변수의 규칙은 그대로 유지되고) 두 번째 매개 변수의 int 형식이어야 한다는 것을 해제한 것입니다. 즉, float, object, ... 사용자 정의 타입 등 원하는 형식으로 할 수 있다는 것입니다.

이것을 보고, 아마도 C++ 언어를 해보셨던 분들은 cout와 같은 기능을 구현할 수 있지 않을까... 기대할 수 있을 것 같은데요,

#include <iostream>
int main()
{
    std::cout << "Hello";
    return 0;
}

아쉽게도, 연산자 자체가 반드시 결과를 받는 대상이 필요하기 때문에 사용법에 약간 제약이 있습니다.

// 정상 컴파일
C d1 = c << 5.8f;

// 컴파일 오류: error CS0201: Only assignment, call, increment, decrement, await, and new object expressions can be used as a statement
c << 5.8f;

오류 메시지에도 나오지만, 대입/호출/증감/await/new 식만 문으로 인정이 되므로 shift 연산자를 쓴 것만으로는 컴파일 오류가 발생합니다. (아마도 나중에 shift 연산자에 한해서만 문으로 인정해 준다면, 그때서야 비로소 C++처럼 cin/cout와 같은 코드를 구현할 수 있을 것입니다. ^^)




참고로, 이 기능이 제안된 이유가 .NET 7에 포함될 Generic Math 때문이라고 합니다. 그런데 한 가지 재미있는 점은, IShiftOperators<TSelf,TResult>와 같은 인터페이스는,

namespace System.Numerics
{
    public interface IShiftOperators<TSelf, TResult> where TSelf : IShiftOperators<TSelf, TResult>
    {
        TResult op_UnsignedRightShift(TSelf value, int shiftAmount);

        public static abstract TResult operator <<(TSelf value, int shiftAmount);
        public static abstract TResult operator >>(TSelf value, int shiftAmount);
    }
}

여전히 두 번째 매개 변수의 타입을 int로 고정했다는 점입니다. 게다가 현재 .NET 7 (v7.0.100-preview.6, "dotnet-sdk-7.0.100-preview.6.22352.1-win-x64.exe")을 기준으로 이번에 새롭게 포함될 Int128 구조체도, 이전의 BigInteger 타입에서도 여전히 int만 받고 있습니다.

// Int128
public static Int128 operator <<(Int128 value, int shiftAmount);
public static Int128 operator >>(Int128 value, int shiftAmount);

// BigInteger
public static BigInteger operator <<(BigInteger value, int shift)
public static BigInteger operator >>(BigInteger value, int shift)

왜 Int128이나 BigInteger를 받는 유형은 제공하지 않는 걸까요? ^^




마지막으로, shift 연산자 재정의 시 두 번째 타입을 int가 아닌 다른 타입으로 정의하는 규칙은 C#만의 제약이라는 점입니다. 즉, IL 수준에서는 어느 타입이든 가능합니다. 실제로 C#에서도 SpecialName 특성을 이용하면 shift 연산자의 두 번째 타입 제약을 벗어날 수 있습니다. 예를 들어 아래와 같이 정의하고,

using System.Runtime.CompilerServices;

namespace ClassLibrary1
{
    public class D
    {
        [SpecialName]
        public static D op_LeftShift(D c, float o)
        {
            Console.WriteLine("shift operator called with " + o);
            return c;
        }
    }
}

이렇게 사용할 수 있습니다.

D d = new D();
var result = d << 5.8f;

여기서 재미있는 점은, "D" 클래스 정의를 반드시 다른 어셈블리로 분리해 놓아야 한다는 것입니다. 즉, 해당 클래스를 사용하는 같은 프로젝트에 "class D"를 정의한 경우에는 다음과 같은 오류가 발생합니다.

D d = new D();

// 컴파일 오류 발생 - error CS0019: Operator '<<' cannot be applied to operands of type 'C' and 'float'
var result = d << 5.8f;

// 같은 어셈블리에 정의한 경우
public class D
{
    [SpecialName]
    public static D op_LeftShift(D c, float o)
    // ...[생략]...
}




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)
1048정성태5/27/201132266개발 환경 구성: 123. Apache 소스를 윈도우 환경에서 빌드하기
1047정성태5/27/201126136.NET Framework: 217. Firebird ALinq Provider - 날짜 필드에 대한 낙관적 동시성 쿼리 오류
1046정성태5/26/201130799.NET Framework: 216. 라이선스까지도 뛰어넘는 .NET Profiler [5]
1045정성태5/24/201131889.NET Framework: 215. 닷넷 System.ComponentModel.LicenseManager를 이용한 라이선스 적용 [1]파일 다운로드1
1044정성태5/24/201132453오류 유형: 122. zlib 빌드 오류 - inflate.obj : error LNK2001: unresolved external symbol _inflate_fast
1043정성태5/24/201131422.NET Framework: 214. 무료 Linq Provider - DbLinq를 이용한 Firebird 접근파일 다운로드1
1042정성태5/23/201137744개발 환경 구성: 122. PHP 소스를 윈도우 환경에서 빌드하기
1041정성태5/22/201128638.NET Framework: 213. Linq To SQL - ALinq Provider를 이용하여 Firebird 사용파일 다운로드1
1040정성태5/21/201138971개발 환경 구성: 121. .NET 개발자가 처음 설치해 본 Apache + PHP [2]
1039정성태5/17/201131669.NET Framework: 212. Firebird 데이터베이스와 ADO.NET [2]파일 다운로드1
1038정성태5/16/201133635개발 환경 구성: 120. .NET 프로그래머에게도 유용한 Firebird 무료 데이터베이스 [2]
1037정성태5/11/201128471개발 환경 구성: 119. Visual Studio Professional 이하 버전에서도 TFS의 정적 코드 분석 정책 연동이 가능할까? [3]
1036정성태5/7/201194269오류 유형: 121. Access DB에 대한 32bit/64bit OLE DB Provider 관련 오류 [11]
1035정성태5/7/201129029오류 유형: 120. File cannot be opened. Ensure it is a valid Data Link file.
1034정성태5/2/201126065.NET Framework: 211. 파일 잠금 없이 .NET 어셈블리의 버전을 구하는 방법 [2]파일 다운로드1
1033정성태5/1/201131777웹: 19. IIS Express - appcmd.exe를 이용한 applicationHost.config 변경 [2]
1032정성태5/1/201128434웹: 18. IIS Express를 NT 서비스로 변경
1031정성태4/30/201129589웹: 17. IIS Express - "IIS Installed Versions Manager Interface"의 IIISExpressProcessUtility 구하는 방법 [1]파일 다운로드1
1030정성태4/30/201151852개발 환경 구성: 118. IIS Express - localhost 이외의 호스트 이름으로 접근하는 방법 [4]파일 다운로드1
1029정성태4/28/201140984개발 환경 구성: 117. XCopy에서 파일/디렉터리 확인 질문 없애기 [2]
1028정성태4/27/201138379오류 유형: 119. Visual Studio 2010 SP1 설치 후 Windows Phone 개발자 도구로 인한 재설치 문제 [3]
1027정성태4/25/201127559디버깅 기술: 40. 상황별 GetFunctionPointer 반환값 정리 - x86파일 다운로드1
1026정성태4/25/201145841디버깅 기술: 39. DebugDiag 1.1을 사용한 덤프 분석 [7]
1025정성태4/24/201127897개발 환경 구성: 116. IIS 7 관리자 - Active Directory Certification Authority로부터 SSL 사이트 인증서 받는 방법 [2]
1024정성태4/22/201129203오류 유형: 118. Windows 2008 서버에서 Event Viewer / PowerShell 실행 시 비정상 종료되는 문제 [1]
1023정성태4/20/201130095.NET Framework: 210. Windbg 환경에서 확인해 본 .NET 메서드 JIT 컴파일 전과 후 [1]
... 151  152  153  154  155  156  157  158  159  [160]  161  162  163  164  165  ...