본문 바로가기

진리는어디에/C#

[C#] dynamic 키워드

DLR(Dynamic Language Runtime) 이란?

C# 프로그래밍 언어의 DLR이란 타입 결정을 컴파일 타임이 아닌 런타임에 하는 기능이다. 타입 키워드로는 dynamic을 사용한다.

  조사 시점 대상 타입
정적 타입 바인딩 컴파일 타임 참조 변수 타입
동적 타입 바인딩(dynamic) 런 타임 메모리에 생성된 실제 객체
using System;

class Base
{
    public virtual void Foo()
    {
        Console.WriteLine("call Base.Foo()");
    }
}

class Derived : Base
{
    public override void Foo()
    {
        Console.WriteLine("call Derived.Foo()");
    }

    public void Bar()
    {
        Console.WriteLine("call Derived.Bar()");
    }
}

class Program
{
    public static void Main()
    {
        Base c = new Derived(); 
        c.Bar(); // 에러. Base 클래스에는 Bar 메소드가 없다
    }
}

28라인에서 부모 클래스인 Base를 이용해 Derived 객체를 저장 후 29라인에서 Derived 클래스의 Bar 메소드를 호출한다. 분명 객체는 Derived긴 하지만 Base 클래스는 자식 클래스의 메소드를 알지 못하기에 컴파일 에러가 발생한다.

하지만 아래와 같이 dynamic으로 객체를 생성하면 컴파일 타임에 타입을 바인딩 하는 것이 아니라 런타임에 바인딩하므로 컴파일 오류가 발생하지 않고, 실행도 정상적으로 된다.

class Program
{
    public static void Main()
    {
        dynamic c = new Derived(); // 런타임에 타입 체크
        c.Bar();
    }
}

// OUTPUT :
// call Derived.Bar()

만일 컴파일 오류가 발생해야 하는 코드라면, 컴파일 오류 대신 런 타임 예외를 발생 시킨다.

class Program
{
    public static void Main()
    {
        dynamic c = new Base();
        c.Bar(); // 컴파일은 잘 됨
    }
}

// OUTPUT :
// Unhandled exception. Microsoft.CSharp.RuntimeBinder.RuntimeBinderException: 'Base' does not contain a definition for 'Bar'
//    at CallSite.Target(Closure , CallSite , Object )
//    at System.Dynamic.UpdateDelegates.UpdateAndExecuteVoid1[T0](CallSite site, T0 arg0)
//    at Program.Main() in D:\helloworld_cs\Program.cs:line 29

사실 위 예제에서는 dynamic을 사용하지 말고 그냥 var를 사용하던지 Derived 클래스 자체를 사용하면 되긴 하지만 핵심은 아래와 같다

"컴파일 타임에 타입 바인딩을 하지 않고 런타임에 한다

부록 1. 같이 읽으면 좋은 글

유익한 글이었다면 공감(❤) 버튼 꾹!! 추가 문의 사항은 댓글로!!