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)
13307정성태4/4/20233890.NET Framework: 2106. C# - .NET Core/5+ 환경의 Windows Forms 응용 프로그램에서 HINSTANCE 구하는 방법
13306정성태4/3/20233682Windows: 243. Win32 - 윈도우(cbWndExtra) 및 윈도우 클래스(cbClsExtra) 저장소 사용 방법
13305정성태4/1/20234053Windows: 242. Win32 - 시간 만료를 갖는 MessageBox 대화창 구현 (쉬운 버전)파일 다운로드1
13304정성태3/31/20234403VS.NET IDE: 181. Visual Studio - C/C++ 프로젝트에 application manifest 적용하는 방법
13303정성태3/30/20233763Windows: 241. 환경 변수 %PATH%에 DLL을 찾는 규칙
13302정성태3/30/20234378Windows: 240. RDP 환경에서 바뀌는 %TEMP% 디렉터리 경로
13301정성태3/29/20234470Windows: 239. C/C++ - Windows 10 Version 1607부터 지원하는 /DEPENDENTLOADFLAG 옵션파일 다운로드1
13300정성태3/28/20234114Windows: 238. Win32 - Modal UI 창에 올바른 Owner(HWND)를 설정해야 하는 이유
13299정성태3/27/20233888Windows: 237. Win32 - 모든 메시지 루프를 탈출하는 WM_QUIT 메시지
13298정성태3/27/20233869Windows: 236. Win32 - MessageBeep 소리가 안 들린다면?
13297정성태3/26/20234535Windows: 235. Win32 - Code Modal과 UI Modal
13296정성태3/25/20233862Windows: 234. IsDialogMessage와 협업하는 WM_GETDLGCODE Win32 메시지 [1]파일 다운로드1
13295정성태3/24/20234146Windows: 233. Win32 - modeless 대화창을 modal처럼 동작하게 만드는 방법파일 다운로드1
13294정성태3/22/20234302.NET Framework: 2105. LargeAddressAware 옵션이 적용된 닷넷 32비트 프로세스의 가용 메모리 - 두 번째
13293정성태3/22/20234371오류 유형: 853. dumpbin - warning LNK4048: Invalid format file; ignored
13292정성태3/21/20234490Windows: 232. C/C++ - 일반 창에도 사용 가능한 IsDialogMessage파일 다운로드1
13291정성태3/20/20234881.NET Framework: 2104. C# Windows Forms - WndProc 재정의와 IMessageFilter 사용 시의 차이점
13290정성태3/19/20234359.NET Framework: 2103. C# - 윈도우에서 기본 제공하는 FindText 대화창 사용법파일 다운로드1
13289정성태3/18/20233558Windows: 231. Win32 - 대화창 템플릿의 2진 리소스를 읽어들여 자식 윈도우를 생성하는 방법파일 다운로드1
13288정성태3/17/20233672Windows: 230. Win32 - 대화창의 DLU 단위를 pixel로 변경하는 방법파일 다운로드1
13287정성태3/16/20233836Windows: 229. Win32 - 대화창 템플릿의 2진 리소스를 읽어들여 윈도우를 직접 띄우는 방법파일 다운로드1
13286정성태3/15/20234281Windows: 228. Win32 - 리소스에 포함된 대화창 Template의 2진 코드 해석 방법
13285정성태3/14/20233863Windows: 227. Win32 C/C++ - Dialog Procedure를 재정의하는 방법파일 다운로드1
13284정성태3/13/20234089Windows: 226. Win32 C/C++ - Dialog에서 값을 반환하는 방법파일 다운로드1
13283정성태3/12/20233628오류 유형: 852. 파이썬 - TypeError: coercing to Unicode: need string or buffer, NoneType found
13282정성태3/12/20233951Linux: 58. WSL - nohup 옵션이 필요한 경우
1  2  3  4  5  6  7  8  9  10  11  12  [13]  14  15  ...