Microsoft MVP성태의 닷넷 이야기
글쓴 사람
정성태 (techsharer at outlook.com)
홈페이지
첨부 파일
 

C# 3.0의 기본 인자(default parameter)가 .NET 1.1/2.0에서도 실행될까?

확인해 보면 될 문제입니다. ^^ 다음과 같이 기본 인자를 사용한 예제를 만들고,

using System;

class Program
{
    static void Main(string[] args)
    {
        Test();
    }

    public static void Test(int n = -1)
    {
        Console.WriteLine(n);
    }
}

컴파일 된 결과를 IL 코드로 보면, 기본 인자가 ".param ... " 구문으로 표현되는 것을 볼 수 있습니다.

.method public hidebysig static void Test([opt] int32 n) cil managed
{
    .param [1] = int32(-1)
    .maxstack 8
    L_0000: nop 
    L_0001: ldarg.0 
    L_0002: call void [mscorlib]System.Console::WriteLine(int32)
    L_0007: nop 
    L_0008: ret 
}

즉, 저 구문을 가진 IL 코드를 .NET 1.1 용 ilasm.exe로 컴파일해보면 될텐데요. 그래서 다음과 같이 ".param [1] = int32(-1)" 코드는 보존하면서 내용상 .NET 1.1과 맞지 않는 부분을 제거해봤습니다.


.assembly extern mscorlib
{
  .publickeytoken = (B7 7A 5C 56 19 34 E0 89 )                         
  .ver 2:0:0:0   // 2.0.0.0으로 되어 있지만 그래도 .NET 1.1 ilasm.exe에서 오류가 발생하지 않습니다.
}

.assembly ConsoleApp1
{
  .custom instance void [mscorlib]System.Reflection.AssemblyCopyrightAttribute::.ctor(string) = ( 01 00 12 43 6F 70 79 72 69 67 68 74 20 C2 A9 20   // ...Copyright .. 
                                                                                                  20 32 30 31 34 00 00 )                            //  2014..
  .custom instance void [mscorlib]System.Reflection.AssemblyDescriptionAttribute::.ctor(string) = ( 01 00 00 00 00 ) 
  .custom instance void [mscorlib]System.Reflection.AssemblyConfigurationAttribute::.ctor(string) = ( 01 00 00 00 00 ) 
  .custom instance void [mscorlib]System.Reflection.AssemblyCompanyAttribute::.ctor(string) = ( 01 00 00 00 00 ) 
  .custom instance void [mscorlib]System.Reflection.AssemblyProductAttribute::.ctor(string) = ( 01 00 13 43 6F 6E 73 6F 6C 65 41 70 70 6C 69 63   // ...ConsoleApplic
                                                                                                61 74 69 6F 6E 31 00 00 )                         // ation1..
  .custom instance void [mscorlib]System.Reflection.AssemblyTitleAttribute::.ctor(string) = ( 01 00 13 43 6F 6E 73 6F 6C 65 41 70 70 6C 69 63   // ...ConsoleApplic
                                                                                              61 74 69 6F 6E 31 00 00 )                         // ation1..
  .custom instance void [mscorlib]System.Reflection.AssemblyTrademarkAttribute::.ctor(string) = ( 01 00 00 00 00 ) 
  .custom instance void [mscorlib]System.Runtime.InteropServices.ComVisibleAttribute::.ctor(bool) = ( 01 00 00 00 00 ) 
  .custom instance void [mscorlib]System.Runtime.InteropServices.GuidAttribute::.ctor(string) = ( 01 00 24 66 30 34 36 37 37 66 65 2D 61 38 32 65   // ..$f04677fe-a82e
                                                                                                  2D 34 66 33 38 2D 39 61 35 33 2D 38 38 63 62 31   // -4f38-9a53-88cb1
                                                                                                  61 39 36 37 37 34 61 00 00 )                      // a96774a..
  .custom instance void [mscorlib]System.Reflection.AssemblyFileVersionAttribute::.ctor(string) = ( 01 00 07 31 2E 30 2E 30 2E 30 00 00 )             // ...1.0.0.0..

  // --- The following custom attribute is added automatically, do not uncomment -------
  //  .custom instance void [mscorlib]System.Diagnostics.DebuggableAttribute::.ctor(valuetype [mscorlib]System.Diagnostics.DebuggableAttribute/DebuggingModes) = ( 01 00 07 01 00 00 00 00 ) 

  .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilationRelaxationsAttribute::.ctor(int32) = ( 01 00 08 00 00 00 00 00 ) 
  .custom instance void [mscorlib]System.Runtime.CompilerServices.RuntimeCompatibilityAttribute::.ctor() = ( 01 00 01 00 54 02 16 57 72 61 70 4E 6F 6E 45 78   // ....T..WrapNonEx
                                                                                                             63 65 70 74 69 6F 6E 54 68 72 6F 77 73 01 )       // ceptionThrows.
  .hash algorithm 0x00008004
  .ver 1:0:0:0
}

.module ConsoleApp1.exe
// MVID: {91066B88-B54D-43E0-8598-3BEDD98ADDA5}
.custom instance void [mscorlib]System.Security.UnverifiableCodeAttribute::.ctor() = ( 01 00 00 00 ) 
.imagebase 0x00400000
.file alignment 0x00000200


.subsystem 0x0003       // WINDOWS_CUI
.corflags 0x00000001    //  ILONLY
// Image base: 0x00E70000


// =============== CLASS MEMBERS DECLARATION ===================

.class private auto ansi beforefieldinit Program
       extends [mscorlib]System.Object
{
  .method private hidebysig static void  Main(string[] args) cil managed
  {
    .entrypoint
    // Code size       9 (0x9)
    .maxstack  8
    IL_0000:  nop
    IL_0001:  ldc.i4.m1
    IL_0002:  call       void Program::Test(int32)
    IL_0007:  nop
    IL_0008:  ret
  } // end of method Program::Main

  .method public hidebysig static void  Test([opt] int32 n) cil managed
  {
    .param [1] = int32(0xFFFFFFFF)   // 기본 인자 값 구문이 있습니다.
    // Code size       9 (0x9)
    .maxstack  8
    IL_0000:  nop
    IL_0001:  ldarg.0
    IL_0002:  call       void [mscorlib]System.Console::WriteLine(int32)
    IL_0007:  nop
    IL_0008:  ret
  } // end of method Program::Test

  .method public hidebysig specialname rtspecialname 
          instance void  .ctor() cil managed
  {
    // Code size       7 (0x7)
    .maxstack  8
    IL_0000:  ldarg.0
    IL_0001:  call       instance void [mscorlib]System.Object::.ctor()
    IL_0006:  ret
  } // end of method Program::.ctor

} // end of class Program


// =============================================================

// *********** DISASSEMBLY COMPLETE ***********************
// WARNING: Created Win32 resource file test.res

이 파일을 test.il로 저장하고 .NET Framework 1.1만 설치된 PC에서 컴파일해 봤는데요.

D:\temp>ilasm test.il /output:test.exe

Microsoft (R) .NET Framework IL Assembler.  Version 1.1.4322.2307
Copyright (C) Microsoft Corporation 1998-2002. All rights reserved.
Assembling 'test.il' , no listing file, to EXE --> 'test.exe'
Source file is ANSI

Assembled method Program::Main
Assembled method Program::Test
Assembled method Program::.ctor
Creating PE file

Emitting members:
Global
Class 1 Methods: 3;
Resolving member refs: 1 -> 1 defs, 0 refs
Writing PE file
Operation completed successfully

C:\temp>dir
 Volume in drive C has no label.
 Volume Serial Number is 5C71-DD99

 Directory of C:\temp

2014-10-03  오전 10:26    <DIR>          .
2014-10-03  오전 10:26    <DIR>          ..
2014-10-03  오전 10:26             2,560 test.EXE
2014-10-03  오전 10:25             4,965 test.il
               2 File(s)          7,525 bytes
               2 Dir(s)  17,396,654,080 bytes free

C:\temp>test
-1

보시는 바와 같이 컴파일도 잘 되고 실행까지 정상동작합니다.

이것이 의미하는 바가 뭐냐면? 기본 인자 기능은 이미 .NET 1.1 초기부터 IL 코드에 구현되어 있었던 것입니다. 하지만, 문법적으로 C#에서는 3.0까지 와서야 비로소 지원하게 된 것이고.

즉, 닷넷 프레임워크는 꽤나 유연하게 디자인 되었던 것입니다. ^^




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







[최초 등록일: ]
[최종 수정일: 10/3/2014]

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

비밀번호

댓글 작성자
 



2014-10-05 04시33분
[Lyn] 아마 C++문법에선 이미 쓰이고 있었으니 C++.net 지원하느라 그랫을거란 추측정도 해보고 갑니다 `-`
[guest]
2014-10-05 04시40분
Lyn님 멋진 의견이군요. ^^ 공감갑니다.
정성태
2014-10-05 04시54분
지금 확인해보니, 그 당시 Managed C++에서는 "C++ managed class"의 경우 기본 인자 정의를 메서드에 포함할 수 없었습니다. (컴파일 오류가 발생하네요. ^^)
정성태

1  2  3  4  5  6  7  8  9  [10]  11  12  13  14  15  ...
NoWriterDateCnt.TitleFile(s)
13391정성태7/14/20233615닷넷: 2132. C# - sealed 클래스의 메서드를 callback 호출했을 때 인라인 처리가 될까요?
13390정성태7/12/20233543스크립트: 53. 파이썬 - localhost 호출 시의 hang 현상
13389정성태7/5/20233611개발 환경 구성: 684. IIS Express로 호스팅하는 웹을 WSL 환경에서 접근하는 방법
13388정성태7/3/20233797오류 유형: 871. 윈도우 탐색기에서 열리지 않는 zip 파일 - The Compressed (zipped) Folder '[...].zip' is invalid. [1]파일 다운로드1
13387정성태6/28/20233854오류 유형: 870. _mysql - Commands out of sync; you can't run this command now
13386정성태6/27/20233973Linux: 61. docker - 원격 제어를 위한 TCP 바인딩 추가
13385정성태6/27/20234156Linux: 60. Linux - 외부에서의 접속을 허용하기 위한 TCP 포트 여는 방법
13384정성태6/26/20233860.NET Framework: 2131. C# - Source Generator로 해결하는 enum 박싱 문제파일 다운로드1
13383정성태6/26/20233593개발 환경 구성: 683. GPU 런타임을 사용하는 Colab 노트북 설정
13382정성태6/25/20233666.NET Framework: 2130. C# - Win32 API를 이용한 윈도우 계정 정보 (예: 마지막 로그온 시간)파일 다운로드1
13381정성태6/25/20234073오류 유형: 869. Fatal Python error: init_fs_encoding: failed to get the Python codec of the filesystem encoding
13380정성태6/24/20233474스크립트: 52. 파이썬 3.x에서의 동적 함수 추가
13379정성태6/23/20233502스크립트: 51. 파이썬 2.x에서의 동적 함수 추가
13378정성태6/22/20233404오류 유형: 868. docker - build 시 "CANCELED ..." 뜨는 문제
13377정성태6/22/20237264오류 유형: 867. 파이썬 mysqlclient 2.2.x 설치 시 "Specify MYSQLCLIENT_CFLAGS and MYSQLCLIENT_LDFLAGS env vars manually" 오류
13376정성태6/21/20233644.NET Framework: 2129. C# - Polly를 이용한 클라이언트 측의 요청 재시도파일 다운로드1
13375정성태6/20/20233286스크립트: 50. Transformers (신경망 언어모델 라이브러리) 강좌 - 2장 코드 실행 결과
13374정성태6/20/20233400오류 유형: 866. 파이썬 - <class 'AttributeError'> module 'flask.json' has no attribute 'JSONEncoder'
13373정성태6/19/20234687오류 유형: 865. 파이썬 - pymssql 설치 관련 오류 정리
13372정성태6/15/20233292개발 환경 구성: 682. SQL Server TLS 통신을 위해 사용되는 키 길이 확인 방법
13371정성태6/15/20233395개발 환경 구성: 681. openssl - 인증서 버전(V1 / V3)
13370정성태6/14/20233536개발 환경 구성: 680. C# - Ubuntu + Microsoft.Data.SqlClient + SQL Server 2008 R2 연결 방법 - TLS 1.2 지원
13369정성태6/13/20233339개발 환경 구성: 679. PyCharm(을 비롯해 JetBrains에 속한 여타) IDE에서 내부 Window들의 탭이 없어진 경우
13368정성태6/13/20233518개발 환경 구성: 678. openssl로 생성한 인증서를 SQL Server의 암호화 인증서로 설정하는 방법
13367정성태6/10/20233673오류 유형: 864. openssl로 만든 pfx 인증서를 Windows Server 2016 이하에서 등록 시 "The password you entered is incorrect" 오류 발생
13366정성태6/10/20233426.NET Framework: 2128. C# - 윈도우 시스템에서 지원하는 암호화 목록(Cipher Suites) 나열파일 다운로드1
1  2  3  4  5  6  7  8  9  [10]  11  12  13  14  15  ...