Microsoft MVP성태의 닷넷 이야기
.NET Framework: 744. C# 6 - Expression bodied function [링크 복사], [링크+제목 복사]
조회: 2503
글쓴 사람
홈페이지
첨부 파일
 

C# 6 - Expression bodied function

아래와 같은 글이 있군요. ^^

식 본문 함수의 최적화
왜 우리는 람다를 더 써야 하는가
; https://phillyai.github.io/2018-05-08-Expression-Bodied-Function/

위의 글에서는 다음의 2가지 메서드를,

int Add(int a, int b) { return a + b; }
int AddLambda(int a, int b) => a + b;

빌드했을 때, 람다 형식으로 작성한 경우 컴파일러가 더 최적화를 잘 해주기 때문이라고 합니다. 실제로 IL 코드로 보면 다음과 같이 차이가 납니다.

.method private hidebysig instance int32 Add(int32 a, int32 b) cil managed
{
    .maxstack 2
    .locals init (
        [0] int32 num)
    L_0000: nop 
    L_0001: ldarg.1 
    L_0002: ldarg.2 
    L_0003: add 
    L_0004: stloc.0 
    L_0005: br.s L_0007
    L_0007: ldloc.0 
    L_0008: ret 
}

.method private hidebysig instance int32 AddLambda(int32 a, int32 b) cil managed
{
    .maxstack 8
    L_0000: ldarg.1 
    L_0001: ldarg.2 
    L_0002: add 
    L_0003: ret 
}

보다시피 람다로 했을 때 코드가 더 간결합니다. 좀 더 기술적인 용어로 첫 번째 Add 메서드는 Fat method 형식이고, 두 번째 Lambda 메서드는 Thin method 형식입니다. 그런데, 사실 이건 Debug 모드로 빌드했기 때문에 나온 결과일 뿐입니다. Release 모드로 빌드하면 다음과 같이 2개 모두 동일한 IL 코드를 볼 수 있습니다.

.method private hidebysig instance int32 Add(int32 a, int32 b) cil managed
{
    .maxstack 8
    L_0000: ldarg.1 
    L_0001: ldarg.2 
    L_0002: add 
    L_0003: ret 
}

.method private hidebysig instance int32 AddLambda(int32 a, int32 b) cil managed
{
    .maxstack 8
    L_0000: ldarg.1 
    L_0001: ldarg.2 
    L_0002: add 
    L_0003: ret 
}

그러니까... 사실 저런 이유로 굳이 람다를 더 쓸 필요는 없습니다.

참고로, 디버그 모드에서 람다 메서드가 더 최적화가 잘 되는 것은, 람다 메서드의 경우 tiny header를 가질 수 있는 요건을 쉽게 충족하기 때문입니다.




"왜 우리는 람다를 더 써야 하는가" 글에서 한 가지 더 이상한 점이 있는데요. 해당 최적화가 Expression에서만 적용되고 Statement에 대해 적용되지 않는다면서 쓴 코드가 바람직하지 않습니다.

void DoLambda() => Do();

위에서 DoLambda의 body 역시 (Statement가 아닌) Expression으로 작성된 것입니다. 저 구문의 영문 이름이 "Expression bodied function"인데요, 즉 저 구문에서는 반드시 Expression만 허용됩니다. 만약 저 코드를 Statement로 만들려면 다음과 같이 코딩해야 하는데,

void DoLambda() => { Do(); } // 컴파일 오류 - Error CS1525 Invalid expression term '{'

그럼 CS1525 컴파일 오류가 발생합니다. 왜냐하면 Expression에서는 블록이 허용되지 않기 때문입니다. (블록은 Statement에만 허용됩니다.)

사실 정확히 말하면 아래의 코드는,

int AddLambda(int a, int b) => a + b;

말 그대로 "Expression bodied function"입니다. 비록 C#의 람다 표현으로 작성하긴 했지만 expression만 허용되는 람다입니다. 반면, 람다 식이 아닌 람다 문을 활용하면 다음과 같이 쓸 수 있습니다.

static void Main(string[] args)
{
    Action action = () => // Statement를 가진 람다 메서드
    {
        Console.WriteLine();
    };
}

그러니까, "왜 우리는 람다를 더 써야 하는가" 글의 제목도 좀 맞지 않습니다. 실제로 저 글의 내용이 맞다고 가정했을 때 좀 더 정확히는 "왜 우리는 Expression bodied function을 사용해야 하는가"라고 해야 합니다.




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





[최초 등록일: ]
[최종 수정일: 6/8/2018 ]

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

비밀번호

댓글 쓴 사람
 




... [46]  47  48  49  50  51  52  53  54  55  56  57  58  59  60  ...
NoWriterDateCnt.TitleFile(s)
11082정성태10/26/20169450.NET Framework: 614. C# - DateTime.Ticks의 정밀도 [4]파일 다운로드1
11081정성태10/26/20165385오류 유형: 364. You need to fix your Microsoft Account for apps on your other devices to be able to launch apps and continue experiences on this device.
11080정성태10/24/20168623Windows: 130. Windows Server 2016 Nano 서버 설치 방법
11079정성태10/21/20165744Windows: 129. Windows Server 2016 설치 CD에 있는 Convert-WindowsImage.ps1 사용 방법 정리
11078정성태10/21/20167157Windows: 128. Windows Server 2016 Nano 서버 VHD 이미지 만드는 방법 - TP5 기준
11077정성태10/21/20167282오류 유형: 363. Active Directory 서버의 NETLOGON 서비스가 멈췄을 때 발생하는 문제
11076정성태10/21/20165279오류 유형: 362. 윈도우 백업 시 오류 - 0x80780040
11075정성태10/20/20166632Windows: 127. Convert-WindowsImage.ps1 사용 방법 정리
11074정성태10/20/201612002Windows: 126. Windows Server 2016 평가판을 정식 버전으로 라이선스 변경하는 방법
11073정성태1/6/20187968.NET Framework: 613. 윈도우 데스크톱 응용 프로그램(예: Console)에서 알림 메시지(Toast notifications) 띄우기파일 다운로드1
11072정성태10/20/20165934VC++: 102. 새로 추가한 ATL COM 객체가 regsvr32.exe로 등록이 안되는 문제
11071정성태10/20/20167081.NET Framework: 612. UWP(유니버설 윈도우 플랫폼) 앱에서 콜백 함수 내에서의 UI 요소 접근 방법 [1]
11070정성태10/21/20165422Windows: 125. 윈도우 서버 2016 마이그레이션
11069정성태3/25/201710035.NET Framework: 611. C++ 개발자들을 위한 C# Thread 동작 방식 [3]
11068정성태5/24/201910975Windows: 124. 윈도우 운영체제의 시간 함수 (5) - TSC(Time Stamp Counter)와 QueryPerformanceCounter [10]파일 다운로드1
11067정성태2/6/20188968Windows: 123. 윈도우 운영체제의 시간 함수 (4) - RTC, TSC, PM Clock, HPET Timer [2]
11066정성태2/6/20187165Windows: 122. 윈도우 운영체제의 시간 함수 (3) - QueryInterruptTimePrecise, QueryInterruptTime 함수파일 다운로드1
11065정성태2/6/20189620Windows: 121. 윈도우 운영체제의 시간 함수 (2) - Sleep 함수의 동작 방식
11064정성태10/19/20196162.NET Framework: 610. C# - WaitOnAddress Win32 API 사용파일 다운로드1
11063정성태2/6/201815689Windows: 120. 윈도우 운영체제의 시간 함수 (1) - GetTickCount와 timeGetTime의 차이점 [5]파일 다운로드1
11062정성태10/12/20165925오류 유형: 361. WCF .svc 호출 시 Could not find a base address that matches scheme net.tcp 예외
11061정성태10/12/201611363오류 유형: 360. IIS - 500.19 오류 (0x80070021)
11060정성태10/12/20165227오류 유형: 359. WCF - .svc 요청시 404 Not Found
11059정성태10/11/20168948.NET Framework: 609. WPF - 다중 스레드 환경에서 데이터 바인딩의 INotifyPropertyChanged.PropertyChanged에 대한 배려 [1]파일 다운로드1
11058정성태10/8/20167602개발 환경 구성: 303. Windows 10 Bash Shell - 한글 환경을 영문으로 바꾸고 싶다면?
11057정성태10/8/20165617오류 유형: 358. Windows 10 bash shell - sudo: unable to resolve host ...
... [46]  47  48  49  50  51  52  53  54  55  56  57  58  59  60  ...