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

... [46]  47  48  49  50  51  52  53  54  55  56  57  58  59  60  ...
NoWriterDateCnt.TitleFile(s)
12496정성태1/19/20219497.NET Framework: 1010. .NET Core 콘솔 프로젝트에서 Kestrel 호스팅 방법 [1]
12495정성태1/19/202111407웹: 40. IIS의 HTTP/2 지원 여부 - h2, h2c [1]
12494정성태1/19/202110722개발 환경 구성: 522. WSL2 인스턴스와 호스트 측의 Hyper-V에 운영 중인 VM과 네트워크 연결을 하는 방법 [2]
12493정성태1/18/20218958.NET Framework: 1009. .NET 5에서의 네트워크 라이브러리 개선 (1) - HTTP 관련 [1]파일 다운로드1
12492정성태1/17/20218396오류 유형: 695. ASP.NET 0x80131620 Failed to bind to address
12491정성태1/16/202110100.NET Framework: 1008. 배열을 반환하는 C# COM 개체의 메서드를 C++에서 사용 시 메모리 누수 현상 [1]파일 다운로드1
12490정성태1/15/20219604.NET Framework: 1007. C# - foreach에서 열거 변수의 타입을 var로 쓰면 object로 추론하는 문제 [1]파일 다운로드1
12489정성태1/13/202110570.NET Framework: 1006. C# - DB에 저장한 텍스트의 (이모티콘을 비롯해) 유니코드 문자가 '?'로 보인다면? [1]
12488정성태1/13/202110818.NET Framework: 1005. C# - string 타입은 shallow copy일까요? deep copy일까요? [2]파일 다운로드1
12487정성태1/13/20219230.NET Framework: 1004. C# - GC Heap에 위치한 참조 개체의 주소를 알아내는 방법파일 다운로드1
12486정성태1/12/202110222.NET Framework: 1003. x64 환경에서 참조형의 기본 메모리 소비는 얼마나 될까요? [1]
12485정성태1/11/202110982Graphics: 38. C# - OpenCvSharp.VideoWriter에 BMP 파일을 1초씩 출력하는 예제파일 다운로드1
12484정성태1/9/202111628.NET Framework: 1002. C# - ReadOnlySequence<T> 소개파일 다운로드1
12483정성태1/8/20218689개발 환경 구성: 521. dotPeek - 훌륭한 역어셈블 소스 코드 생성 도구
12482정성태1/8/202110257.NET Framework: 1001. C# - 제네릭 타입/메서드에서 사용 시 경우에 따라 CS8377 컴파일 에러
12481정성태1/7/20219929.NET Framework: 1000. C# - CS8344 컴파일 에러: ref struct 타입의 사용 제한 메서드파일 다운로드1
12480정성태1/6/202112555.NET Framework: 999. C# - ArrayPool<T>와 MemoryPool<T> 소개파일 다운로드1
12479정성태1/6/20219962.NET Framework: 998. C# - OWIN 예제 프로젝트 만들기
12478정성태1/5/202111595.NET Framework: 997. C# - ArrayPool<T> 소개파일 다운로드1
12477정성태1/5/202113917기타: 79. github 코드 검색 방법 [1]
12476정성태1/5/202110653.NET Framework: 996. C# - 닷넷 코어에서 다른 스레드의 callstack을 구하는 방법파일 다운로드1
12475정성태1/5/202113221.NET Framework: 995. C# - Span<T>와 Memory<T> [1]파일 다운로드1
12474정성태1/4/202110655.NET Framework: 994. C# - (.NET Core 2.2부터 가능한) 프로세스 내부에서 CLR ETW 이벤트 수신 [1]파일 다운로드1
12473정성태1/4/20219490.NET Framework: 993. .NET 런타임에 따라 달라지는 정적 필드의 초기화 유무 [1]파일 다운로드1
12472정성태1/3/20219778디버깅 기술: 178. windbg - 디버그 시작 시 스크립트 실행
12471정성태1/1/202110273.NET Framework: 992. C# - .NET Core 3.0 이상부터 제공하는 runtimeOptions의 rollForward 옵션 [1]
... [46]  47  48  49  50  51  52  53  54  55  56  57  58  59  60  ...