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"의 경우 기본 인자 정의를 메서드에 포함할 수 없었습니다. (컴파일 오류가 발생하네요. ^^)
정성태

... 31  32  33  34  35  36  37  38  39  [40]  41  42  43  44  45  ...
NoWriterDateCnt.TitleFile(s)
12648정성태5/16/20218284사물인터넷: 66. PC -> FTDI -> NodeMCU v1 ESP8266 기기를 UART 핀을 연결해 직렬 통신하는 방법파일 다운로드1
12647정성태5/15/20219555.NET Framework: 1058. C# - C++과의 연동을 위한 구조체의 fixed 배열 필드 사용파일 다운로드1
12646정성태5/15/20218648사물인터넷: 65. C# - Arduino IDE의 Serial Monitor 기능 구현파일 다운로드1
12645정성태5/14/20218341사물인터넷: 64. NodeMCU v1 ESP8266 - LittleFS를 이용한 와이파이 접속 정보 업데이트파일 다운로드1
12644정성태5/14/20219540오류 유형: 719. 윈도우 - 제어판의 "프로그램 및 기능" / "Windows 기능 켜기/끄기" 오류 0x800736B3
12643정성태5/14/20218733오류 유형: 718. 서버 유형의 COM+ 사용 시 0x80080005(Server execution failed) 오류 발생
12642정성태5/14/20219648오류 유형: 717. The 'Microsoft.ACE.OLEDB.12.0' provider is not registered on the local machine.
12641정성태5/13/20219357디버깅 기술: 179. 윈도우용 .NET Core 3 이상에서 Windbg의 sos 사용법
12640정성태5/13/202112285오류 유형: 716. RDP 연결 - Because of a protocol error (code: 0x112f), the remote session will be disconnected. [1]
12639정성태5/12/20219187오류 유형: 715. Arduino: Open Serial Monitor - The module '...\detection.node' was compiled against a different Node.js version using NODE_MODULE_VERSION
12638정성태5/12/202110123사물인터넷: 63. NodeMCU v1 ESP8266 - 펌웨어 내 파일 시스템(SPIFFS, LittleFS) 및 EEPROM 활용
12637정성태5/10/20219711사물인터넷: 62. NodeMCU v1 ESP8266 보드의 A0 핀에 다중 아날로그 센서 연결 [1]
12636정성태5/10/20219999사물인터넷: 61. NodeMCU v1 ESP8266 보드의 A0 핀 사용법 - FSR-402 아날로그 압력 센서 연동파일 다운로드1
12635정성태5/9/20219235기타: 81. OpenTabletDriver를 (관리자 권한으로 실행하지 않고도) 관리자 권한의 프로그램에서 동작하게 만드는 방법
12634정성태5/9/20218285개발 환경 구성: 572. .NET에서의 신뢰도 등급 조정 - 외부 Manifest 파일을 두는 방법파일 다운로드1
12633정성태5/7/20219797개발 환경 구성: 571. UAC - 관리자 권한 없이 UIPI 제약을 없애는 방법
12632정성태5/7/202110040기타: 80. (WACOM도 지원하는) Tablet 공통 디바이스 드라이버 - OpenTabletDriver
12631정성태5/5/20219922사물인터넷: 60. ThingSpeak 사물인터넷 플랫폼에 ESP8266 NodeMCU v1 + 조도 센서 장비 연동파일 다운로드1
12630정성태5/5/202110202사물인터넷: 59. NodeMCU v1 ESP8266 보드의 A0 핀 사용법 - CdS Cell(GL3526) 조도 센서 연동파일 다운로드1
12629정성태5/5/202111962.NET Framework: 1057. C# - CoAP 서버 및 클라이언트 제작 (UDP 소켓 통신) [1]파일 다운로드1
12628정성태5/4/20219921Linux: 39. Eclipse 원격 디버깅 - Cannot run program "gdb": Launching failed
12627정성태5/4/202110620Linux: 38. 라즈베리 파이 제로 용 프로그램 개발을 위한 Eclipse C/C++ 윈도우 환경 설정
12626정성태5/3/202110567.NET Framework: 1056. C# - Thread.Suspend 호출 시 응용 프로그램 hang 현상 (2)파일 다운로드1
12625정성태5/3/20219498오류 유형: 714. error CS5001: Program does not contain a static 'Main' method suitable for an entry point
12624정성태5/2/202113363.NET Framework: 1055. C# - struct/class가 스택/힙에 할당되는 사례 정리 [10]파일 다운로드1
12623정성태5/2/20219979.NET Framework: 1054. C# 9 최상위 문에 STAThread 사용 [1]파일 다운로드1
... 31  32  33  34  35  36  37  38  39  [40]  41  42  43  44  45  ...